Python使用winIco编写一个托盘图标不停闪烁的小程序

昨天测试了使用Tkinter来编写简单的托盘程序,总体说来是非常方便的,代码在Windows和Linux下都能很好地工作。

Windows下,Tkinter可以使用封装好的winIco API: tktable/winico
下载最新的0.6即可。 (05年发布,有人提到64位系统下无法正常工作,我没有测试)
另外,还可以参考这个TCL项目: http://cran.r-project.org/web/packages/tcltk2/

里面有个package ico1.0,是在winIco的基础上修改的,但是它的接口已经改变,如果你对TCL脚本熟悉,建议使用。

1. 解压dll到tcl文件夹

下载winIco0.6之后,直接解压到tcl文件夹下,类似: D:\Python27\tcl\winico0.6。
测试python下是否可用:

>>> from Tkinter import Tk
>>> root = Tk()
>>> root.tk.call('package', 'require', 'Winico')
'0.6'

2. 合成不同的图标到一个ico文件

程序在托盘不停闪烁图标,利用了在一个ico文件中,可以集成多个不同大小、颜色的图标资源。
我使用了Greenfish Icon Editor Pro来合并图标文件:
join-icons
第一个图标对应的是#0,第二个图标对应的是#1。还可以继续添加其他需要使用到的图标。

3. python调用winIco

winIco提供的接口非常简单:https://www.lijiejie.com/python/winico/winico.html

  1. 使用createfrom可以直接从ico文件创建图标资源。
  2. load命令可以从exe或dll中加载图标资源
  3. info命令则是获取某个句柄对应的若干图标资源的信息:  包括编号、大小、颜色深度
  4. taskbar命令用于添加、修改、删除托盘图标,重要的参数包括了-callback(回调函数)、-pos(图标资源序列号)、-text(托盘图标的提示文本),在回调函数中,可以通过%m参数来传递窗口消息。

在添加托盘图标时,可以用-callback参数指定回调函数,比如右键点击弹出菜单。

我写了一个简单的示例程序:
flash-trayicon-sample
这个地球图标会不停闪烁(0.5秒切换一次),右键单击,可弹出一个菜单。 源代码在这里

python和tkinter写了一个豆瓣音乐下载工具

前天自己的阿里妈妈账号再次被冻结了,好不容易有5000多收入,一下又没了。

没办法,还是拿自己的一点小手艺,赚点吃饭的钱,花一天时间写了这个小工具。

douban-music-downloader

可以下载豆瓣的红心兆赫、豆瓣小站大部分专辑。下载任意兆赫的功能没有写,时间有限。

douban-downloader-main

这个程序我希望能够收费提供,所以虽然公开代码,但并不希望你生成无限制的exe免费提供,请谅解。

Tkinter是single-threaded,记住这一点比较重要。 对于耗时的操作,比如下载,需要创建新的线程来完成。

我在程序启动时创建了5个daemon线程,用于下载MP3,一般,5个线程就足够达到较好的下载效率。

windows可执行文件 (请注意,文件夹名称中不能存在中文)

下载源代码 (如果你做了任何改进,欢迎提交给我。 :))

Python命名空间和作用域的基本认识和一点小魔法

作为初学者,简单总结自己对Python命名空间(namespace)和作用域(scope)的认识。

Python在名称空间搜寻变量和函数的顺序可以认为是:

函数内部 -> (嵌套)父函数内部 -> 模块内部 ->  built_in内置模块

1. 函数内部(local)

简单举例说明:

x = 123

def func():
    x = 456
    print 'inner x =', x

func()
print 'outer x =', x

输出:

inner x = 456
outer x = 123

模块级变量x的值是123,而在函数func内部,local变量x的值是456。可以看到,函数是没有改变外部x的值的。

2. 父函数内部 继续阅读Python命名空间和作用域的基本认识和一点小魔法

python sys.setdefaultencoding的一点小魔法

python中调用sys.setdefaultencoding方法可以修改默认编码。

但是这个方法调用有一些特别。在python解释器中执行:

>>> import sys
>>> dir(sys)

输出为:

['__displayhook__', '__doc__', '__egginsert', '__excepthook__', '__name__', '__p
ackage__', '__plen', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache
', '_current_frames', '_getframe', '_mercurial', 'api_version', 'argv', 'builtin
_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayh
ook', 'dllhandle', 'dont_write_bytecode', 'exc_clear', 'exc_info', 'exc_type', '
excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_
repr_style', 'getcheckinterval', 'getdefaultencoding', 'getfilesystemencoding',
'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'gettrace', 'getw
indowsversion', 'hexversion', 'long_info', 'maxint', 'maxsize', 'maxunicode', 'm
eta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', '
prefix', 'ps1', 'ps2', 'py3kwarning', 'setcheckinterval', 'setprofile', 'setrecu
rsionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'subversion', 'version', '
version_info', 'warnoptions', 'winver']

会看到实际上sys模块中并没有这个所谓的setdefaultencoding方法。

文档中描述为:这个方法是为site模块的调用而准备的,而一旦被调用之后,它将会被从sys的名称空间中抹掉。

This function is only intended to be used by the site module 
implementation and, where needed, by sitecustomize. Once used 
by the site module, it is removed from the sys module’s namespace.

而如果确实有需要调用这个方法,可以使用reload再次导入这个模块:

import sys  

print 'old encoding value:', sys.getdefaultencoding()
reload(sys)
sys.setdefaultencoding('utf8')
print 'new encoding value:', sys.getdefaultencoding()

输出为:

old encoding value: ascii
new encoding value: utf8

Python Tkinter写的一个POST工具[源代码]

昨天想复习一下使用Tkinter开发GUI程序,练手写了一个简单的POST工具。    源代码

必须的package有:

前者用于在linux下显示GIF窗口图标,后者用于检查文本编码,以便完成自动解码unicode。

写代码过程中遇到的问题有:

  1.  linux和mac下的图标问题
  2.  窗口屏幕居中的问题
  3.  Tkinter不支持多线程

对于第三个问题,因为Tkinter是单线程的,因此捕获到按钮点击后,需要创建另一个线程完成post动作。

自然,也可以在command对应的函数中完成HTTP请求了,但会面临窗口不能及时响应的问题。

也就是说,在HTTP请求结束前的一两秒内,窗口是无响应的。

另外,也正因为Tkinter不支持多线程。

错误提示将以红色的文本显示在Response相应的文本框中,而不是消息框提示。

在另一个线程改变文本框的内容是安全的,但创建MessageBox就不是这么回事了。

TkPostTool

Tkinter窗口在屏幕居中的问题

为了让程序窗口在不同的平台和计算机上都能良好的显示,需要考虑:

1. 窗口的大小

2. 窗口的位置

对于第一点,因为默认字体不同,应该尽量避免固定长宽,而让geometry manager(图形管理器)自己去计算所需的大小。但可以设置各个部件之间的间隙大小。

对于这一点,我还想提一下tkinter中的entry和text这两个widget,他们的height和width都是表示可以输入的英文字数,而不是像素值。只有这样,同样的文本内容,才可以在windows、linux下展现一致。而不会windows下在A处换行了,而ubuntu却在B处换行。

Tkinter的窗口屏幕居中有点烦人,没有现成的method,但我找到了一种可行的方法。简单说明:

1. 屏幕的分辨率是非常容易获取到的,直接通过root.winfo_screenwidth()、root.winfo_screenheight() 继续阅读Tkinter窗口在屏幕居中的问题