设为首页 收藏本站
查看: 2514|回复: 0

[经验分享] 用python写桌面天气预报,自己的学习曲线。

[复制链接]

尚未签到

发表于 2015-4-24 11:20:19 | 显示全部楼层 |阅读模式
自从接触python,就被他优雅而简洁的代码所吸引。
举个例子:



arr = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 ]
#如果想要将arr中大于10的项取出来,然后每项乘以2,组成一个新的列表arr2,在python里只需要这么一样就行了:
arr2 = [x * 2 for x in arr if x > 10 ]
如果用其他语言来写的吗,不会这么简洁,美观。

python还有更强大的特性,它有非常丰富的类库,以至于它几乎能完成大多数语言都能完成的工作。比如写网站、写软件、写游戏、写服务器、嵌入式开发等。

最近出门总是天公不作美,仔细想想是忘了看天气预报了。于是就想找个桌面天气软件,这样一打开电脑就能看到天气了,关电脑前也可以看一眼明天的天气。
在百度里面找到了好几款桌面天气软件,大都不完美,不是自己想要的效果(有的是界面不美观,有的是里面夹杂着其他程序过于累赘,有的是快捷键冲突了,有的是只能看当前天气不能看明天天气等等)。
当然也有一款个人感觉挺满意的。后来想了下,既然python这么强大,那么用python写一个这样的软件岂不是更好,想要什么功能,就写什么功能。

于是就开始了我的python桌面天气预报的庞大工程。(为什么说庞大呢,后面就知道了。)

由于我是做界面开发的,之前学python的时候就顺便学了wxPython这个强大的类库。于是就用wxPython来写。

写之前肯定先要解决几个问题:1、天气数据的获取与分析。2、能够贴在桌面上,鼠标穿透,像桌面背景一样。3、要背景透明。


1、很容易解决网上的api一大堆,可以百度一下。
2、我也找到了办法就是用User32.dll里面的SetWindowLongA方法。具体的python代码是这么写的


selfWnd = ctypes.windll.user32.FindWindowA("wxWindowClassNR", None)
Ret = ctypes.windll.user32.GetWindowLongA(selfWnd, -20)
Ret = Ret | 0x00080000 | 0x00000020
ctypes.windll.user32.SetWindowLongA(selfWnd, -20, Ret)
3、这个是最麻烦的了,也是浪费我时间最多的一个。

最开始在wxPython里面找到一个叫SetTransparent()的方法,试了下发现是设置整个窗口的透明度的,不是设置背景的透明度的。又想到把一张png图片作为背景图片不就行了吗。
用尽了各种方法后发现即使用png作为窗口的背景,窗口原来的背景也会同时存在的。相当于就是用一张图片浮在窗口背景上了,没达到我要的背景透明的效果。
后来发现wxPython有个ShapedWindow的例子,可以实现用图片作为背景的效果。
代码就不贴了,效果是这样子的
DSC0000.jpg
跟我要的效果很接近。如果再把这张图片做成半透明的,那么就是我要的效果了。
于是百度、谷歌狂搜,也没找到个方法来,最后从各种搜索结果中发现了两个问题:
1、这张作为背景的图片是不支持alpha通道的,即使图片有透明度也不行,虽然wxPython有将png图片显示在程序里的例子,但是作为背景的话,是不可能的。
2、这张图片显示区域之外的部分是显示不出来的。如图:
DSC0001.jpg
文字其实是有红框那么长,但是由于在这张图片的区域之外,所以就没有显示出来。

后来在网上发现有个用tkinter实现的背景透明为文字不透明的方法,如图:
DSC0002.jpg
基本上是我想要的效果。
于是又重燃了我学习tkinter的决心,放弃用wxPython了,之前一直没有研究这个python内置的Gui工具。

放弃用wxPython来写这个程序还有其他方面的原因:
1、不能实现我想要的用透明背景图片作为窗口的背景。
2、wxStaticText这个文本显示控件,是有背景的,默认的背景是从父级继承过来的。网上有办法可以擦除背景,但是对于右对齐的文字来说,在重绘的时候,会出现文字重叠如图:
正常情况下: DSC0003.png ,重叠的情况: DSC0004.png ,这个文字被重绘了好几遍。
3、由于要实现鼠标穿透效果,需要获取窗口句柄,而wxPython没有任何一个方法可以返回自己的窗口句柄。
虽然可以通过 selfWnd = ctypes.windll.user32.FindWindowA("wxWindowClassNR", None) 来获取句柄,
但是这个方法不可靠,因为窗口类名wxWindowClassNR不是唯一的,用spy++可以看到有好多窗口的类名都是
这个名字。这种方法会造成,返回的不是自己窗口的句柄,而是别人窗口的句柄。


俗话说 磨刀不误砍柴工,我把tkinter入门,各个组件的介绍,使用方法,例子都看了一遍,都一一测试过,防止学的时候没学好,理解不透彻,导致用的时候碰到各种问题。

.........

n天后,已经学的差不多了,就开始用tkinter来写这个程序。窗口透明效果很容易就实现了。
代码如下:


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

import Tkinter

root = Tkinter.Tk()
#这一行可以隐藏掉窗口边框和标题栏
root.overrideredirect(True)
root["width"] = 100
root["height"] = 80
#这一行可以将所有的白色透明掉
root.attributes("-transparentcolor","white")
root["background"] = "white"

x, y = 0, 0

def StartMove(event):
    global x, y
    x = event.x
    y = event.y
def StopMove(event):
    x = None
    y = None
def OnMotion(event):
    global x, y
    deltax = event.x - x
    deltay = event.y - y
    _x = root.winfo_x() + deltax
    _y = root.winfo_y() + deltay
    root.geometry("+%s+%s" % (_x, _y))


label = Tkinter.Label(root, text="ddddd", bg="white")
label.place(x=10, y=10, anchor=Tkinter.NW)

root.bind("", StartMove)
root.bind("", StopMove)
root.bind("", OnMotion)

root.mainloop()
这是效果图:
DSC0005.png 后面的颜色是我的桌面,可以看到,背景完全透明了。文字也没有像wxPython那样被切割掉。
但是有一个很明显的问题,文字变得不清晰了。
这是在win7下的效果但是在xp下就显示正常了,如图:
DSC0006.jpg
现在都用win7了 不可能写个程序只能在xp下运行吧。所以得找解决办法。
又百度、谷歌狂搜,最后还是在python自带的文档里找到了这么一句话:
like anti-aliased font rendering under X11, window transparency (on X11 you will need a composition window manager) will be missing.
意思是字体抗锯齿、窗口透明在window下将会丢失。
就说是tkinter里面是没有抗锯齿和窗口透明功能的。之前的透明方法只是把特定颜色透明了,并不是真正意义上的透明。tkinter里面是没有alpha通道的。所以用半透明图片做背景是不可能实现的。

不过tkinter相比wxPython来说有个优点就是它可以返回窗口句柄了,print hex(root.winfo_id())


无奈之下,只好再找其他的python GUI工具了。
接下来装了个pygtk,但是装上之后,导入时会报错,大概意思是缺少某个dll文件。我都是按照教程安装的。
后来在虚拟机的xp系统里面装了下,却没有报错。
真是奇怪了,同样的几个文件,同样的安装顺序,在win7下装完后有问题,在xp下就正常运行。
我估计是某个pygtk用到的dll文件在win7和xp里面不一致导致的。
搜了下发现网上也有人遇到同样情况的,但是基本上找不到解决方案,或者说很难找,于是就暂时放弃了。

之后又装了个pyqt,安装过程也很方便,有个独立安装包,直接安装就行,可以正常运行。
看了里面的例子后顿时感觉:“梦里寻她千百度,蓦然回首,那人却在灯火阑珊处。”
真是太好了,由于我是做actionscript开发的,发现qt几乎能实现flash的所有功能。

再次,磨刀不误砍柴工。先看基础吧。
这个不错,可供大家参考http://jimmykuu.sinaapp.com/static/PyQt4_Tutorial/html/index.html

经过一番努力和研究之后,终于实现了我想要的效果了。
先贴图看下效果:
DSC0007.jpg

pyqt里面实现窗口无边框的是:



self.setWindowFlags(QtCore.Qt.FramelessWindowHint|QtCore.Qt.SubWindow|QtCore.Qt.WindowStaysOnBottomHint)
实现背景透明的是:


self.setAttribute(QtCore.Qt.WA_TranslucentBackground, True)
我写了个函数来实现鼠标穿透的切换:


def toggleMouseThrough(self, through=None):
    if through==None:
        self.mouseThrough = not self.mouseThrough
    else:
        self.mouseThrough = bool(through)
    selfWnd = int(self.winId())
    ret = ctypes.windll.user32.GetWindowLongA(selfWnd, -20)
    if self.mouseThrough:
        ret = ret | 0x00000020
        self.SetTopTexts(self.miniWeatherArr[0].data)
    else:
        ret = ret & ~0x00000020
    ctypes.windll.user32.SetWindowLongA(selfWnd, -20, ret)

源码放在百度网盘里了,有想研究的可以看下。
http://pan.baidu.com/s/1mntsc

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-60267-1-1.html 上篇帖子: python通过webservice连接cmdbuild 下篇帖子: [摘]Python 程序员的进化
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表