这系列教程完全以代码的形式来写的,目标是:读者看代码和注释就可以理解 代码的意思。
但这里的读者需要具备的几项技能:
他不是一本经过文字润色的文章,全部是代码,作者在必要的时候使用注释来解释;
以组件为章节进行介绍,每个组件又分为不同的例子,各个例子可以单独使用,分别使用序号标各个例子的使用“注释+序号”的格式表示开始,下一个例子的开始为上一个例子的结束; 熟悉python语言的基础,如果还没有,先看一下python的教程吧,英文官方对界面编程有一定的了解,知道基本的概念就可以了;
对Tk有兴趣,别以为她是已经过时的技术,如果丧失了学习的兴趣,那肯定无法完成了; 不要以Ctrl+C/Ctrl+V的方式使用本教程(虽然它可以这样直接运行),自己输入,你会发现自己安装了python2.5且确认安装了Tkinter模块(默认就安装了,如果你没有强制的把它去掉的话),如果在阅读教程中有不明白的,不要强迫自己,直接跳过去,继续下一个内容。 (http://docs.python.org/tut/tut.html);
原来也会犯这样的错误;
下载python2.5(http://www.python.org/download/);
Tkinter教程系列教程的特点:
注;
全部使用结构化编程(SP),没有面向对象的概念(OO);
基本上包含了TKinter的所有的控件,根据每个控件的使用方法,选择性的介绍了其属性和方法,没
有
全
部
介
绍
,
全
部
的
介
绍
查
看
Tkinter
的
官
方
参
考
(http://www.pythonware.com/library/tkinter/introduction/);
例子不是百分百的完美,甚至有的例子没有按照Tkinter参考的描述完成,原因由于作者没有看懂:(
参考书籍:http://www.pythonware.com/library/tkinter/introduction/,如有冲突以Tkinter参考为准
最后祝各位Tk一路快乐!
Python中的\"copy\"与\"reference\" (2007-09-22 20:08)
'''
Python中的“copy”与“reference”
每个对象对应一个实体,一个实体可以对应多个别名,python没有像C++语言的参数和引用的之分,python统一使用别名(aliase)。
对于简单(或者称为基本)和不可修改类型,python使用“copy”别名的方式;对于复合和可修改类型,python使用“reference”别名
1.使用“copy”别名,必须使用基本类型(int,float,string,tuple) '''
# 整型数值
x = 10 y = x print x,y # 10,10
y = 40 print x,y # 10,40
# x的值还为10,y的值变为40 '''
y = x是对象复制,x与y分别使用不同的对象实体,故y只改变后,x值还为10 ''' '''
2.使用“reference”别名,类型为自定义一个Point '''
#定义一个Point class Point: pass;
a = Point() a.x = 10
# 给对象Point再加一个别名 b = a
# 打印原始数据 print a.x,b.x
# 使用别名b访问Point对象 b.x = 40
# 打印修改后的Point对象 print a.x,b.x ''' b = a为Point对象实体添加另外的一个别名,当再次调用b.x = 40时,b指向的实体改变,其x属性重新赋值为40.因x与y指向同一个实体, 故a的属性x也改为40 ''' Python面向对象初级教程 (2007-09-23 02:38)
'''
python不单单用作结构化编程,她还是面向对象的高级语言,支持类(class),本文将介绍Python面向对象的编程思想。类(class)被用来用户自定义数据类型,用户使用类(class)来组织数据,管理数据。 类(class)的定义
类(class)的属性(attribute) 类(class)的方法(method) 类(chalss)成员的控制域 类(class)的继承与组合
1.类的定义,类的定义使用关键字class,后跟类的名称,及\":\"。如定义一个Point类 '''
# 定义一个空的类,没有任何属性与方法 class Point: pass '''
向类中添加类属性(有的称之为类成员),类属性与其它的变量使用方法一致,第一次使用便是对此变量的定义,属性的作用域为整个类,即这个类的所有方法可以访问此属性,定义Point属性的属性x和y '''
# 定义一个空的类,没有任何属性与方法 class Point:
# 定义x和y坐标 x = 10 y = 10 '''
类方法为特殊的函数,其定义方法与函数类似,但有一个默认的参数self,表示此类对象的实例(instance),定义类的方法,设置x的方法setX和获取x的方法getX。 '''
# 定义一个完整的类,包含属性与方法 class Point:
# 定义x和y坐标 x = 10 y = 10
def setX(self,x_): self.x = x_ def getX(self): return self.x def setY(self,y_): self.y = y_ def getY(self):
return self.y
def setXY(self,x_,y_): self.setX(x_) self.setY(y_) '''
注意:这个类方法如何访问类属性,使用self.x,而不是x。python类方法与C++不同,类的成员方法不会自动使用类的属性,必须使用self明确指定。如果只使用x,则在setX函数中创建了一个变量x,并将其值设置为_x。
同样对于类方法之间互相访问时也必须使用self指定为调用的为类的方法。 ''' # python还支持在类定义块之外定义方法,这个方法满足类方法,例如先定义一个函数outX def out_setX(self,x_): self.x = x_
# 然后定义类,并将类成员h赋值为out_setX class Point: x = 10 y = 10
setX = out_setX '''
创建一个类的对象,并访问这个类的属性和方法 '''
# 创建Point的一个对象 pt = Point() # 设置坐标x的值 pt.x = 10
# 获取坐标x的值 print pt.x
# 访问对象的方法 pt.setX(20) '''
C++中有函数重载的概念,python则没有,如果有如下函数定义 def f():
print 'f' def f(x):
print 'f(x)' f() f(20)
出错信息
TypeError: f() takes exactly 1 argument (0 given)
由于f先定义为无参数的函数,后有定义为带一个参数的函数,及f被重新定义,所以再次调用
f()时,解释器抱怨找不到无参数名称为f的函数。但可以使用如下
def f():
print 'f' def f(x):
print 'f(x)'
#此id已被重新定义,可以这样解释: ## x = 10 ## x = 20
#此时x的值已经被改编为20,已不再是10无法在访问10 #f() f(20) ''' '''
C++还有构造函数(constructor)的概念,这个函数为一特殊的函数,在创建对象时自动被调用,python中也没有构造函数,有一个功能类似的函数,用来初始化类属性,这个函数为: __init__,如下代码,在创建对象时将类属性初始化 '''
class Point: x = 10 y = 10
def __init__(self,x_,y_): self.x = x_ self.y = y_
# 将坐标(x,y)设置为(20,20) pt = Point(20,20) print pt.x,pt.y '''
类的成员(属性和方法),python默认使用public,即属性与方法可以被直接访问,这一点与C++也不相同,python改变属性可见性的是通过表示ID,私有成员以\"前导字符_至少两个,后尾字符_最多一个\"表示,如定义私有属性和私有方法 私有属性:
__pri1 前导字符个数2 ___pri2 前导字符个数3
____pri3_ 前导字符个数4,后尾字符1 共有属性:
_pub1 前导字符1
___pri2__ 前导字符3,后尾字符2 '''
class Point:
# 私有属性,只能通过类方法访问 __x = 10
# 私有方法,可被其他类方法调用 def __setX(self,x_):
# 访问私有属性 self.__x = x_ def setX(self,x_): # 调用私有方法 self.__setX(x_) def getX(self): # 访问私有属性 return self.__x pt = Point() # 直接访问__x # pt.__x
# 解释器会抱怨没有__x属性
# AttributeError: Point instance has no attribute '__x' # 访问私有方法 # pt.__setX(10)
# 解释器还是会抱怨没有属性__setX(python视方法也为属性) print pt.getX() pt.setX(20) print pt.getX() '''
在类中可以定义属性,有此类创建的对象可以使用此类的所有属性,除此之外,python还支持动态向类或类对象中添加属性。向类中添加属性,其后所有的类对象便可以使用新添加的属性;若向类对象中添加属性,只用此类对象可以使用此属性 '''
'''向类中添加属性''' class Point:pass
# 向类中添加属性z Point.z = 30 # 创建类对象 pt = Point() pp = Point() # 访问类属性z print Point.z
# 访问类对象属性z,pp与pt均含有属性z print pt.z,pp.z
'''向类对象中添加属性''' class Point:pass
pt = Point() pp = Point()
# 向类对象中添加属性
pt.z = 10
# 访问类的属性 # print Point.z
# 解释器抱怨没有属性z
#AttributeError: class Point has no attribute 'z' print pt.z
# 访问pp对象的属性z # print pp.z
#解释器抱怨没有z属性
#AttributeError: Point instance has no attribute 'z' '''
类的继承与组合,实现代码重用。不用copy&paste代码,当创建新类时,不必全部从头开始,尽可能的使用已有代码。TIC++中使用两种方法:一种称为组合(composition);另一种称为继承(inheritance)。 继承语法格式:
class class DerivedClassName(BaseClassName):pass '''
'''子类访问父类属性''' class Point: x = 10 y = 20
def setX(self,x_): self.x = x_ def getX(self): return self.x
class Circle(Point): r = 5
# 创建父类对象 pt = Point() # 创建子类对象 cl = Circle() # 访问父类的属性 print cl.x,cl.y # 访问父类的方法 cl.setX(40) print cl.x,cl.y
'''重载父类属性,访问Circle属性''' class Point: x = 10
y = 20
def setX(self,x_): self.x = x_ def getX(self): return self.x
class Circle(Point): x = 40 y = 50 r = 5
# 创建父类对象 pt = Point() # 创建子类对象 cl = Circle()
# 访问Circle类的属性 print cl.x,cl.y # 40,50
'''重载父类属性,访问父类Point属性''' class Point: x = 10 y = 20
def setX(self,x_): self.x = x_ def getX(self): return self.x
class Circle(Point): x = 40 y = 50 r = 5
# 访问父类的属性 def callBase(self):
# x,y已经被Circle重载,显示使用父类访问父类属性 print Point.x,Point.y # 创建子类对象 cl = Circle()
# 访问Point类的属性 cl.callBase() # 10,20 '''
C++语言中的子类会自动调用父类的构造函数,python中的__init__不会自动调用父类的__init__,如果要调用必须显示的调用父类的__init__
'''
'''重载父类属性,访问父类属性''' class Point:
def __init__(self): print 'Point'
class Circle(Point): def __init__(self):
# 显示调用父类的__init__函数 Point.__init__(self) print 'Circle' cl = Circle() # Point # Circle '''
C++有抽象类,此类只定义函数接口(有的称之为interface),其具体的实现有子类来实现,python没有抽象类,实现方法:将基类函数接口设置为None,如果使用此基类创建对象,调用此函数时会出现异常,具体实现由其子类实现 ''' #抽象类
class Graphic: draw = None
# 实现Graphic的draw class Point(Graphic): x = 10 y = 10
# 将draw赋值
def __init__(self):
self.draw = self.__draw # 实现抽象接口 def __draw(self):
print self.x,self.y # 实现Graphic的draw class Circle(Point): r = 5
# 将draw赋值
def __init__(self):
self.draw = self.__draw # 实现抽象接口 def __draw(self):
print self.x,self.y,self.r # 创建各个类的对象 gp = Graphic() pt = Point()
cl = Circle() #gp.draw() # 函数调用出错
#TypeError: 'NoneType' object is not callable # 调用Point的draw pt.draw()
# 调用Circle的draw cl.draw() '''
类的组合:类的另一种重用方式,《C++ Primer plus》有介绍适用于此设计方法的类与类之间的关系,称之为”has-a“关系,与继承”is-a“关系相对应。 ”is-a“关系:
圆柱(cylinder)is-a特殊的圆(circle),它含有高度属性,圆(circle)为圆柱(cylinder)的父类;
圆(circle)is-a特殊的点,它含有半径属性,点(point)为圆(circle)的父类 '''
# 定义父类及子类 class Point:pass
class Circle(Point):pass class Cylinder(Circle):pass '''
”has-a\"关系:
画布(canvas)上可以绘制各种图形(如:点(point)、圆(circle)和圆柱(cylinder)等)。绘图程序
定义如下关系 '''
# 定义容器类 class Canvas:
# 包含三个类对象Point、Circle和Cylinder pt = Point() cl = Circle() cy = Cylinder() def __init__(self): pass
Tkinter教程之Label篇 (2007-09-28 00:26)
#Tkinter教程之Label篇 '''1.Label的第一个例子 text属性使用方法 '''
#要使用Tk模块,除非你不想使用这个模块,那整个教程就不需要看了 from Tkinter import * #初始化Tk root = Tk()
#创建一个label,使用编码,到现在为止还没有使用过直接通过“drag-and-drop”就可以完成的IDE。
label = Label(root,text = 'Hello Tkinter') #显示label,必须含有此语句 label.pack() #root.pack()
#但root是不需要(严格地说是必须不这样使用),否则解释器抱怨 #进入消息循环 root.mainloop() #控件的显示步骤: #1.创建这个控件
#2.指定这个空间的master,即这个控件属于哪一个 #3.告诉GM(geometry manager)有一个控件产生了 '''
还有更简单的一个例子:将‘Hello Tkinter’打印到标题上,Label也不用创建了 from Tkinter import * root = Tk()
root.title('hello Tkinter') root.mainloop()
再没法儿简化了,就这样吧 '''
'''2.在label上使用内置位图 bitmap的使用方法 '''
from Tkinter import * #初始化Tk root = Tk()
#创建一个label,使用编码,到现在为止还没有使用过直接通过“drag-and-drop”就可以完成的IDE。
label = Label(root,bitmap = 'error') #上面的代码使用了内置位图error
#显示label,必须含有此语句
label.pack()
#进入消息循环 root.mainloop() '''
其他可用的位图: * error * hourglass * info
* questhead * question * warning * gray12 * gray25 * gray50 * gray75
若要查看各自的效果,可以使用相应的名称将bitmpa = 'error'替换。 据说还可以使用自己指定的位图文件,网上找了一下,格式如下: Label(root, bitmap=\"@/path/bitmapname\")
不过我试了一下,从来没有成功过,我已经将位图该为单色的了:(
另:还有的网上的文章说明如何使用PhotoImage和BitmapImage显示bmp或gif文件,提到一点
防止图像文件被python自动回收(garbage collected),应将bmp或gif放到全局(global)或实体
(instance)中,使用如下两种方法,仍未奏效: '''
#使用image属性
# bm = PhotoImage(file = 'c:\\\\python.gif') # label = Label(root,image = bm) # label.bm = bm #错误信息:
#TclError: image \"pyimageXX\" doesn't exist #使用bitmap属性
# bm = BitmapImage(file='c:\\\\python2.bmp') # label = Label(root,bitmap=bm) # label.bm = bm
# label.pack() #错误信息:
#TclError: format error in bitmap data '''
虽然二者均没有起作用,还是要说明一下,bitmap与image的关系,如果同时指定这两参数,image 优先。
'''
'''3.改变控件的前景色和背景色 fg:前景色 bg:背景色
设置背景色的一个大的用处是:可以判断控件的大小(不同的控件使用不同的颜色,后续内容
可以使用此特性来调试container) '''
from Tkinter import * root = Tk()
#在创建Label时指定各自使用的颜色 '''可以使用的颜色值:''' #使用颜色名称
Label(root,fg = 'red',bg = 'blue',text = 'Hello I am Tkinter').pack() #使用颜色值#RRGGBB
Label(root,fg = 'red',bg = '#FF00FF',text = 'Hello I am Tkinter').pack() #使用系统相关的颜色值(Windows),不建议使用这样的值,不利于平台移植 Label(root,fg = 'red',bg = 'SystemButtonShadow',text = 'Hello I am Tkinter').pack() root.mainloop() '''
(1).使用颜色名称 Red Green Blue Yellow LightBlue ......
(2).使用#RRGGBB
label = Label(root,fg = 'red',bg = '#FF00FF',text = 'Hello I am Tkinter') 指定背景色为绯红色
(3).除此之外,Tk还支持与OS相关的颜色值,如Windows支持 SystemActiveBorder, SystemActiveCaption, SystemAppWorkspace, SystemBackground, ...... '''
'''4.设置宽度与高度 width: 宽度 height: 高度 '''
from Tkinter import * root = Tk()
#创建三个Label,分别显示red,blue,yellow
#注意三个Label的大小,它们均与文本的长度有关
Label(root,text = 'red',bg = 'red').pack() Label(root,text = 'blue',bg = 'blue').pack() Label(root,text = 'yellow',bg = 'yellow').pack()
#再创建三个Label,与上次不同的是这三个Label均使用width和heigth属性 #三个Label的大小由width和height指定
Label(root,bg = 'red',width = 10,height = 3).pack() Label(root,bg = 'blue',width = 10,height = 3).pack() Label(root,bg = 'yellow',width = 10,height = 3).pack() root.mainloop()
'''5.同时使用图像与文本
compound: 指定文本(text)与图像(bitmap/image)是如何在Label上显示,缺省为None, 当指定image/bitmap时,文本(text)将被覆盖,只显示图像了。可以使用的值: left: 图像居左 right: 图像居右 top: 图像居上 bottom:图像居下
center:文字覆盖在图像上 bitmap/image:
显示在Label上的图像 text:
显示在Label上的文本
label = Label(root,text = 'Error',compound = 'left',bitmap = 'error') '''
from Tkinter import * root = Tk()
#演示compound的使用方法 #图像与文本在Label中的位置 #图像居下
Label(root,text = 'botton',compound = 'bottom',bitmap = 'error').pack() #图像居上
Label(root,text = 'top',compound = 'top',bitmap = 'error').pack() #图像居右
Label(root,text = 'right',compound = 'right',bitmap = 'error').pack() #图像居左
Label(root,text = 'left',compound = 'left',bitmap = 'error').pack() #文字覆盖在图像上
Label(root,text = 'center',compound = 'center',bitmap = 'error').pack()
#消息循环
root.mainloop()
'''6.文本的多行显示
在Tk004中,使用width和heigth来指定控件的大小,如果指定的大小无法满足文本的要求是,会出现
什么现象呢?如下代码:
Label(root,bg = 'welcome to jcodeer.cublog.cn',width = 10,height = 3).pack() 运行程序,超出Label的那部分文本被截断了,常用的方法是:使用自动换行功能,及当文本长度大于
控件的宽度时,文本应该换到下一行显示,Tk不会自动处理,但提供了属性: wraplength: 指定多少单位后开始换行 justify: 指定多行的对齐方式
ahchor: 指定文本(text)或图像(bitmap/image)在Label中的显示位置 可用的值: e w n s ne se sw sn center 布局如下图
nw n ne w center e sw s se '''
from Tkinter import * root = Tk()
#左对齐,文本居中
Label(root,text = 'welcome to jcodeer.cublog.cn',bg = 'yellow',width = 40,height = 3,wraplength = 80,justify = 'left').pack() #居中对齐,文本居左
Label(root,text = 'welcome to jcodeer.cublog.cn',bg = 'red',width = 40,height = 3,wraplength = 80,anchor = 'w').pack() #居中对齐,文本居右
Label(root,text = 'welcome to jcodeer.cublog.cn',bg = 'blue',width = 40,height = 3,wraplength = 80,anchor = 'e').pack()
root.mainloop() '''
运行一下程序就可以直观的看出,justify与anchor的区别了:一个用于控制多行的对齐;另一个用于
控制整个文本块在Label中的位置
'' Tkinter教程之Button篇(1) (2007-09-29 00:16)
#JTkinter教程之Button篇(1) #Button功能触发事件
'''1.一个简单的Button应用''' from Tkinter import * #定义Button的回调函数 def helloButton():
print 'hello button' root = Tk()
#通过command属性来指定Button的回调函数
Button(root,text = 'Hello Button',command = helloButton).pack() root.mainloop() '''
执行的结果:每次点击一次,程序向标准输出打印'hello button',以上为Button使用方法,可以
再做一下简化,如不设置Button的回调函数,这样也是允许的但这样的结果与Label没有什么太
大的区别,只是外观看起来有所不同罢了,失去了Button的作用。 from Tkinter import * root = Tk()
#下面的relief = FLAT设置,就是一个Label了!!!
Button(root,text = 'hello button',relief=FLAT).pack() root.mainloop() '''
'''2.测试Button的relief属性'''
#运行下面的代码可以看到Button的各个不同效果,均没有回调函数。 from Tkinter import * root = Tk()
#flat, groove, raised, ridge, solid, or sunken
Button(root,text = 'hello button',relief=FLAT).pack() Button(root,text = 'hello button',relief=GROOVE).pack() Button(root,text = 'hello button',relief=RAISED).pack() Button(root,text = 'hello button',relief=RIDGE).pack() Button(root,text = 'hello button',relief=SOLID).pack() Button(root,text = 'hello button',relief=SUNKEN).pack()
root.mainloop() '''
Button显示图像
image:可以使用gif图像,图像的加载方法img = PhotoImage(root,file = filepath
bitmap:使用X11 格式的bitmap,Windows的Bitmap没法显示的,在Windows下使用GIMP2.4将windows
Bitmap转换为xbm文件,依旧无法使用.linux下的X11 bitmap编辑器生成的bitmap还没有测试,但可
以使用内置的位图。 (1).使用位图文件
bp = BitmapImage(file = \"c:\\\\python2.xbm\") Button(root,bitmap = bp).pack() (2).使用位图数据 BITMAP = \"\"\"
#define im_width 32 #define im_height 32
static char im_bits[] = {
0xaf,0x6d,0xeb,0xd6,0x55,0xdb,0xb6,0x2f, 0xaf,0xaa,0x6a,0x6d,0x55,0x7b,0xd7,0x1b, 0xad,0xd6,0xb5,0xae,0xad,0x55,0x6f,0x05, 0xad,0xba,0xab,0xd6,0xaa,0xd5,0x5f,0x93, 0xad,0x76,0x7d,0x67,0x5a,0xd5,0xd7,0xa3, 0xad,0xbd,0xfe,0xea,0x5a,0xab,0x69,0xb3, 0xad,0x55,0xde,0xd8,0x2e,0x2b,0xb5,0x6a, 0x69,0x4b,0x3f,0xb4,0x9e,0x92,0xb5,0xed, 0xd5,0xca,0x9c,0xb4,0x5a,0xa1,0x2a,0x6d, 0xad,0x6c,0x5f,0xda,0x2c,0x91,0xbb,0xf6, 0xad,0xaa,0x96,0xaa,0x5a,0xca,0x9d,0xfe, 0x2c,0xa5,0x2a,0xd3,0x9a,0x8a,0x4f,0xfd, 0x2c,0x25,0x4a,0x6b,0x4d,0x45,0x9f,0xba, 0x1a,0xaa,0x7a,0xb5,0xaa,0x44,0x6b,0x5b, 0x1a,0x55,0xfd,0x5e,0x4e,0xa2,0x6b,0x59, 0x9a,0xa4,0xde,0x4a,0x4a,0xd2,0xf5,0xaa }; \"\"\"
使用tuple数据来创建图像
bmp = BitmapImage(data = BITMAP) Button(root,bitmap = bmp) '''
'''3.与Label一样,Button也可以同时显示文本与图像,使用属性compound''' from Tkinter import *
root = Tk()
#图像居下,居上,居右,居左,文字位于图像之上
Button(root,text = 'botton',compound = 'bottom',bitmap = 'error').pack() Button(root,text = 'top',compound = 'top',bitmap = 'error').pack() Button(root,text = 'right',compound = 'right',bitmap = 'error').pack() Button(root,text = 'left',compound = 'left',bitmap = 'error').pack() Button(root,text = 'center',compound = 'center',bitmap = 'error').pack()
#消息循环
root.mainloop()
'''4.控件焦点问题 创建三个Button,各自对应回调函数;将第二个Button设置焦点,程序运行是按“Enter”,判断
程序的打印结果 '''
from Tkinter import *
def cb1():
print 'button1 clicked' def cb2(event):
print 'button2 clicked' def cb3():
print 'button3 clicked'
root = Tk()
b1 = Button(root,text = 'Button1',command = cb1) b2 = Button(root,text = 'Button2') b2.bind(\" b3 = Button(root,text = 'Button3',command = cb3) b1.pack() b2.pack() b3.pack() b2.focus_set() root.mainloop() ''' 上例中使用了bind方法,它建立事件与回调函数(响应函数)之间的关系,每当产生 后,程序便自动的调用cb2,与cb1,cb3不同的是,它本身还带有一个参数----event,这个参数传递 响应事件的信息。 ''' from Tkinter import * def printEventInfo(event): print 'event.time = ' , event.time print 'event.type = ' , event.type print 'event.WidgetId = ', event.widget print 'event.KeySymbol = ',event.keysym root = Tk() b = Button(root,text = 'Infomation') b.bind(\" b.pack() b.focus_set() root.mainloop() ''' 犯了个错误,将 被调用。程序打印出了event的信息。 ''' Tkinter教程之Button篇(2) (2007-09-29 22:55) # Tkinter教程之Button篇(2) '''5.指定Button的宽度与高度 width: 宽度 heigth: 高度 使用三种方式: 1.创建Button对象时,指定宽度与高度 2.使用属性width和height来指定宽度与高度 3.使用configure方法来指定宽度与高度 ''' from Tkinter import * root = Tk() b1 = Button(root,text = '30X1',width = 30,height = 2) b1.pack() b2 = Button(root,text = '30X2') b2['width'] = 30 b2['height'] = 3 b2.pack() b3 = Button(root,text = '30X3') b3.configure(width = 30,height = 3) b3.pack() root.mainloop() # 上述的三种方法同样也适合其他的控件 '''6.设置Button文本在控件上的显示位置 anchor: 使用的值为:n(north),s(south),w(west),e(east)和ne,nw,se,sw,就是地图上的标识位置了,使用 width和height属性是为了显示各个属性的不同。 ''' from Tkinter import * root = Tk() #简单就是美! for a in ['n','s','e','w','ne','nw','se','sw']: Button(root, text = 'anchor', anchor = a, width = 30, height = 4).pack() #如果看的不习惯,就使用下面的代码。 # Button(root,text = 'anchor',width = 30,height =4).pack() # Button(root,text = 'anchor',anchor = 'center',width = 30,height =4).pack() # Button(root,text = 'anchor',anchor = 'n',width = 30,height = 4).pack() # Button(root,text = 'anchor',anchor = 's',width = 30,height = 4).pack() # Button(root,text = 'anchor',anchor = 'e',width = 30,height = 4).pack() # Button(root,text = 'anchor',anchor = 'w',width = 30,height = 4).pack() # Button(root,text = 'anchor',anchor = 'ne',width = 30,height = 4).pack() # Button(root,text = 'anchor',anchor = 'nw',width = 30,height = 4).pack() # Button(root,text = 'anchor',anchor = 'se',width = 30,height = 4).pack() # Button(root,text = 'anchor',anchor = 'sw',width = 30,height = 4).pack() root.mainloop() '''7.改变Button的前景色与背景色 fg: 前景色 bg:背景色 ''' from Tkinter import * root = Tk() bfg = Button(root,text = 'change foreground',fg = 'red') bfg.pack() bbg = Button(root,text = 'change backgroud',bg = 'blue') bbg.pack() root.mainloop() '''8.设置Button的边框 bd(bordwidth):缺省为1或2个像素 ''' # 创建5个Button边框宽度依次为:0,2,4,6,8 from Tkinter import * root = Tk() for b in [0,1,2,3,4]: Button(root, text = string(b), bd = b).pack() root.mainloop() '''9.设置Button的风格 relief/raised/sunken/groove/ridge ''' from Tkinter import * root = Tk() for r in ['raised','sunken','groove','ridge']: Button(root, text = r, relief = r, width = 30).pack() root.mainloop() '''10.设置Button状态 normal/active/disabled ''' from Tkinter import * root = Tk() def statePrint(): print 'state' for r in ['normal','active','disabled']: Button(root, text = r, state = r, width = 30, command = statePrint).pack() root.mainloop() #例子中将三个Button在回调函数都设置为statePrint,运行程序只有normal和active激活了回调函数,而disable按钮则没有,对于暂时不 #需要按钮起作用时,可以将它的state设置为disabled属性 '''11.绑定Button与变量 设置Button在textvariable属性 ''' from Tkinter import * root = Tk() def changeText(): if b['text'] == 'text': v.set('change') print 'change' else: v.set('text') print 'text' v = StringVar() b = Button(root,textvariable = v,command = changeText) v.set('text') b.pack() root.mainloop() ''' 将变量v与Button绑定,当v值变化时,Button显示的文本也随之变化 ''' Tkinter教程之Entry篇 (2007-09-30 19:49) #Tkinter教程之Entry篇 #Entry用来输入单行文本 '''1.第一个Entry程序''' from Tkinter import * root = Tk() Entry(root,text = 'input your text here').pack() root.mainloop() #上面的代码目的是创建一个Entry对象,并在Entry上显示'input your text here',运行此代码,并没有看到文本的显示,由此可知与Lable和Button不同,Entry的text属性不可以设置Entry的文本 '''2.在Entry中设定初始值,使用textvariable将变量与Entry绑定''' from Tkinter import * root = Tk() e = StringVar() entry = Entry(root,textvariable = e) e.set('input your text here') entry.pack() root.mainloop() #上面的例子中将变量e与Entry绑定,然后将e的值设置为'input your text here',程序运行时的初始值便设置了。 '''3.设置为只读Entry. Entry的另一个比较有用的属性,设置为只读,不允许用户对它的值改变。 设置state属性为'readonly' ''' from Tkinter import * root = Tk() e = StringVar() entry = Entry(root,textvariable = e) e.set('input your text here') entry.pack() entry['state'] = 'readonly' root.mainloop() #实际上Entry的属性值可以使用的也为normal/active/disabled,'readonly'与disabled一样 '''4.设置为密码输入框 #将Entry作为一个密码输入框来使用,即不显示用户输入的内容值,用特定符号代替。使 用用属性 show来指定。 ''' from Tkinter import * root = Tk() e = StringVar() entry = Entry(root,textvariable = e) e.set('input your text here') entry.pack() #使用*来显示输入的内容,如果喜欢可以改为其它字符 entry['show'] = '*' #分别使用*#$显示输入的文本内容 for mask in ['*','#','$']: e = StringVar() entry = Entry(root,textvariable = e) e.set('password') entry.pack() entry['show'] = mask root.mainloop() '''5.验证输入的内容是否符合要求。 使用validate来校验输入的内容 使用validate方法来限制输入的内容 这是一个有问题的例子,无法调用validateText回调函数 ‘''' from Tkinter import * root = Tk() e = StringVar() def validateText(contents): print contents return contents.isalnum() entry = Entry(root,validate = 'key',textvariable = e,validatecommand = validateText) entry.pack() root.mainloop() ''' 文档中说明使用validate来接受的事件,使用validatecommand来确定输入的内容是否合法,但 如何传入参数?没找到相应的说明 ''' #还有其他的属性fg/bg/relief/width/height/justify/state使用方法与Button相同, 不再举例。 Tkinter教程之Checkbutton篇 (2007-09-30 20:37) #Tkinter教程之Checkbutton篇 #Checkbutton又称为多选按钮,可以表示两种状态:On和Off,可以设置回调函数,每当点击此按钮时回调函数被调用 '''1.一个简单的Checkbutton例子''' #创建一个Checkbutton,显示文本为\"python\" from Tkinter import * root = Tk() Checkbutton(root,text = 'python').pack() root.mainloop() '''2.设置Checkbutton的回调函数''' from Tkinter import * def callCheckbutton(): print 'you check this button' root = Tk() Checkbutton(root,text = 'check python',command = callCheckbutton).pack() root.mainloop() #不管Checkbutton的状态如何,此回调函数都会被调用 '''3.通过回调函数改变Checkbutton的显示文本text的值''' from Tkinter import * def callCheckbutton(): #改变v的值,即改变Checkbutton的显示值 v.set('check Tkinter') root = Tk() v = StringVar() v.set('check python') #绑定v到Checkbutton的属性textvariable Checkbutton(root,text = 'check python',textvariable = v,command = callCheckbutton).pack() root.mainloop() '''4.上述的textvariable使用方法与Button的用法完全相同,使用此例是为了区别Checkbutton的另外的一个属性variable,此属性与textvariable不同,它是与这个控件本身绑定,Checkbutton自己有值:On和Off值,缺省状态On为1,Off为0,如:''' #显示Checkbutton的值 from Tkinter import * root = Tk() #将一整数与Checkbutton的值绑定,每次点击Checkbutton,将打印出当前的值 v = IntVar() def callCheckbutton(): print v.get() Checkbutton(root, variable = v, text = 'checkbutton value', command = callCheckbutton).pack() root.mainloop() '''5.Checkbutton的值不仅仅是1或0,可以是其他类型的数值,可以通过onvalue和offvalue属性设置Checkbutton的状态值,如下代码将On设置为'python',Off值设置为'Tkinter',程序的打印值将不再是0或1,而是'Tkinter’或‘python’''' from Tkinter import * root = Tk() #将一字符串与Checkbutton的值绑定,每次点击Checkbutton,将打印出当前的值 v = StringVar() def callCheckbutton(): print v.get() Checkbutton(root, variable = v, text = 'checkbutton value', onvalue = 'python', #设置On的值 offvalue = 'tkinter Tkinter教程之Radiobutton篇 (2007-09-30 23:39) #Tkinter教程之Radiobutton篇 #Radiobutton为单选按钮,即在同一组内只能有一个按钮被选中,每当选中组内的一个按钮时,其它的按钮自动改为非选中态,与其他控件不同的是:它有组的概念 '''1.创建一个简单的Radiobutton''' from Tkinter import * root = Tk() Radiobutton(root,text = 'python').pack() Radiobutton(root,text = 'tkinter').pack() Radiobutton(root,text = 'widget').pack() root.mainloop() #不指定绑定变量,每个Radiobutton自成一组 '''2.创建一个Radiobutton组,使用绑定变量来设置选中哦的按钮''' from Tkinter import * root = Tk() #创建一个Radiobutton组,创建三个Radiobutton,并绑定到整型变量v #选中value=1的按钮 v = IntVar() v.set(1) for i in range(3): Radiobutton(root,variable = v,text = 'python',value = i).pack() root.mainloop() '''3.创建两个不同的组''' from Tkinter import * root = Tk() vLang = IntVar() vOS = IntVar() vLang.set(1) vOS.set(2) for v in [vLang,vOS]: #创建两个组 for i in range(3): #每个组含有3个按钮 Radiobutton(root, variable = v, value = i, text = 'python' + str(i) ).pack() root.mainloop() #不同的组,各个按钮互不影响。 '''4.如果同一个组中的按钮使用相同的alue,则这两个按钮的工作方式完全相同''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() v = IntVar() v.set(1) for i in range(3): Radiobutton(root, variable = v, value = 1, text = 'python' + str(i) ).pack() for i in range(3): Radiobutton(root, variable = v, value = i, text = 'python' + str(2 + i) ).pack() root.mainloop() #上述的例子中共有4个alue为1的值,当选中其中的一个时,其他三个也会被选中;选中除了这四个只外的按钮时,四个按钮全部取消 '''5.与Checkbutton类似,每个Radiobutton可以有自己的处理函数,每当点击按钮时,系统会调用相应的处理函数''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() v = IntVar() v.set(0) def r1(): print 'call r1' def r2(): print 'call r2' def r3(): print 'call r3' def r4(): print 'call r4' i = 0 #创建8个按钮,其中两个两个的value值相同 for r in [r1,r2,r3,r4]: Radiobutton(root, variable = v, text = 'radio button', value = i, command = r ).pack() Radiobutton(root, variable = v, text = 'radio button', value = i, command = r ).pack() i += 1 root.mainloop() #注意虽然同时可以选中两个按钮,但每次点击按钮,执行的代码只有一次 '''6.Radiobutton另一个比较实用的属性是indicatoron,缺省情况下为1,如果将这个属性改为0,则其外观是Sunken''' from Tkinter import * root = Tk() v = IntVar() v.set(1) for i in range(3): Radiobutton(root, variable = v, indicatoron = 0, text = 'python & tkinter', value = i ).pack() root.mainloop() #Radiobutton表示按钮的弹起或按下两种状态 Tkinter教程之Listbox篇 (2007-10-01 11:40) #Tkinter教程之Listbox篇 #Listbox为列表框控件,它可以包含一个或多个文本项(text item),可以设置为单选或多选 '''1.创建一个Listbox,向其中添加三个item''' from Tkinter import * root = Tk() lb = Listbox(root) for item in ['python','tkinter','widget']: lb.insert(END,item) lb.pack() root.mainloop() '''2.创建一个可以多选的Listbox,使用属性selectmaod''' from Tkinter import * root = Tk() lb = Listbox(root,selectmode = MULTIPLE) for item in ['python','tkinter','widget']: lb.insert(END,item) lb.pack() root.mainloop() # 依次点击这三个item,均显示为选中状态。 # 属性MULTIPLE允许多选,每次点击item,它将改变自己的当前选状态,与Checkbox有点相似 '''3.这个属性selectmode还可以设置为BROWSE,可以通过鼠标来移动Listbox中的选中位置(不是移动item),这个属性也是Listbox在默认设置的值,这个程序与1.程序运行的结果的一样的。''' from Tkinter import * root = Tk() lb = Listbox(root,selectmode = BROWSE) for item in ['python','tkinter','widget']: lb.insert(END,item) lb.pack() root.mainloop() #使用鼠标进行拖动,可以看到选中的位置随之变化。 # 与BROWSE相似 的为SINGLE,但不支持鼠标移动选中位置。 from Tkinter import * root = Tk() lb = Listbox(root,selectmode = BROWSE) for item in ['python','tkinter','widget']: lb.insert(END,item) lb.pack() root.mainloop() #使用鼠标进行拖动,没有任何变化 '''4.使用selectmode = EXPANDED使用Listbox来支持Shift和Control。''' from Tkinter import * root = Tk() lb = Listbox(root,selectmode = EXTENDED) for item in ['python','tkinter','widget']: lb.insert(END,item) lb.pack() root.mainloop() #运行程序,点中“python\",shift + 点击\"widget\",会选中所有的item #运行程序,点中\"python\",control + 点击\"widget\",会选中python和widget,第二项tkinter处于非选中状态 '''5.向Listbox中添加一个item''' # 以上的例子均使用了insert来向Listbox中添加 一个item,这个函数有两个属性一个为添加的索引值,另一个为添加的项(item) # 有两个特殊的值ACTIVE和END,ACTIVE是向当前选中的item前插入一个(即使用当前选中的索引作为插入位置);END是向 # Listbox的最后一项添加插入一项 # 先向Listbox中追加三个item,再在Listbox开始添加三项 from Tkinter import * root = Tk() lb = Listbox(root) for item in ['python','tkinter','widget']: lb.insert(END,item) #只添加一项将[]作为一个item #lb.insert(0,['linux','windows','unix']) #添加三项,每个string为一个item lb.insert(0,'linux','windows','unix') lb.pack() root.mainloop() '''6.删除Listbox中的项,使用delete,这个函数也有两个参数,第一个为开始的索引值;第二个为结束的索引值,如果不指定则只删除第一个索引项。''' from Tkinter import * root = Tk() lb = Listbox(root) for i in range(10): lb.insert(END,str(i)) lb.delete(1,3) lb.pack() root.mainloop() #运行程序,只有值0456789,1-3被删除 #删除全部内容,使用delete指定第一个索引值0和最后一个参数END,即可 #lb.delete(0,END) '''7.选中操作函数,使用函数实现。selection_set函数有两个参数第一个为开始的索引;第二个为结束的索引,如果不指定则只选中第一个参数指定的索引项''' from Tkinter import * root = Tk() lb = Listbox(root) for i in range(10): lb.insert(END,str(i)) lb.selection_set(0,10) lb.pack() root.mainloop() # 程序运行结果,选中了所有的项。 此代码并未指定Listbox为MULTIPLE或EXTENDED,查通过selection_set仍旧可以对Listbox #进行操作。 #与之相对的便是取消选中的函数了,参数与selection_set在参数相同,如下代码取消索引从0-3在状态 from Tkinter import * root = Tk() lb = Listbox(root) for i in range(10): lb.insert(END,str(i)) lb.selection_set(0,10) lb.selection_clear(0,3) lb.pack() root.mainloop() '''8.得到当前Listbox中的item个数''' from Tkinter import * root = Tk() lb = Listbox(root) for i in range(10): lb.insert(END,str(i)) lb.delete(3) print lb.size() lb.pack() root.mainloop() #首先向Listbox中添加 了10个item,然后删除索引为3在item,最后的打印结果为9,即当前的Listbox中只有9项 '''9.返回指定索引的项''' from Tkinter import * root = Tk() lb = Listbox(root) for i in range(10): lb.insert(END,str(i*100)) print lb.get(3) lb.pack() root.mainloop() #返回值为300 #get也为两个参数的函数,可以返回多个项(item),如下返回索引值3-7的值 from Tkinter import * root = Tk() lb = Listbox(root) for i in range(10): lb.insert(END,str(i*100)) print lb.get(3,7) lb.pack() root.mainloop() #返回值为('300', '400', '500', '600', '700'),是一个tuple类型。 '''10.返回当前返回的项的索引,不是item的值''' from Tkinter import * root = Tk() lb = Listbox(root) for i in range(10): lb.insert(END,str(i*100)) lb.selection_set(3,8) print lb.curselection() lb.pack() root.mainloop() #返回值为('3', '4', '5', '6', '7', '8'),而不是('300','400','500','600','700','800'),哑然无法直接得到各项的值,知道了索引,得到值 #就很容易了:lb.get()就可以实现。 '''11.判断 一个项是否被选中,使用索引。''' from Tkinter import * root = Tk() lb = Listbox(root) for i in range(10): lb.insert(END,str(i*100)) lb.selection_set(3,8) print lb.selection_includes(8) print lb.selection_includes(0) lb.pack() root.mainloop() #返回结果:True Flase,即8包含在选中的索引中,0不包含在选中的索引中 '''12.Listbox与变量绑定''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() v = StringVar() lb = Listbox(root,listvariable = v) for i in range(10): lb.insert(END,str(i*100)) #打印当前列表中的项值 print v.get() #输出:('0', '100', '200', '300', '400', '500', '600', '700', '800', '900') #改变v的值,使用tuple可以与item对应 v.set(('1000','200')) #结果只有两项了1000和200 lb.pack() root.mainloop() '''13.Listbox与事件绑定''' # 它不支持command属性来设置回调函数了,使用bind来指定回调函数,打印当前选中的值 # -*- coding: cp936 -*- from Tkinter import * root = Tk() def printList(event): print lb.get(lb.curselection()) lb = Listbox(root) lb.bind(' lb.insert(END,str(i*100)) lb.pack() root.mainloop() #还有一个比较实用的功能没有介绍:滚动条的添加,留到后面介绍Scrollbar的时候再一并介绍 Tkinter教程之Scale篇 (2007-10-01 16:21) '''Tkinter教程之Scale篇''' #Scale为输出限定范围的数字区间,可以为之指定最大值,最小值及步距值 '''1.创建一个Scale''' from Tkinter import * root = Tk() Scale(root).pack() root.mainloop() #创建一个垂直Scale,最大值为100,最小值为0,步距值为1。这个参数设置也就是Scale的缺省设置了。 '''2.改变这三个参数,生成 一个水平Scale,最小值为-500,最大值为500,步距值为5''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() Scale(root, from_ = -500, #设置最大值 to = 500, #设置最小值 resolution = 5, #设置步距值 orient = HORIZONTAL #设置水平方向 ).pack() root.mainloop() #注意from_的使用方式,在其后添加了\"_\",避免与关键字from的冲突 '''3.Scale绑定变量''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() v = StringVar() Scale(root, from_ = 0, #设置最小值 to = 100.0, #设置最大值 resolution = 0.0001, #设置步距值 orient = HORIZONTAL, #设置水平方向 variable = v #绑定变量 ).pack() print v.get() root.mainloop() #v的值与Scale的值一致 '''4.使用回调函数打印当前的值''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() def printScale(text): print 'text = ',text print 'v = ',v.get() v = StringVar() Scale(root, from_ = 0, #设置最小值 to = 100.0, #设置最大值 resolution = 0.0001, #设置步距值 orient = HORIZONTAL, #设置水平方向 variable = v, #绑定变量 command = printScale #设置回调函数 ).pack() print v.get() root.mainloop() #这个回调函数有一个参数,这个值是当前的Scale的值,每移动一个步距就会调用一次这个函数,只保证最后一个肯定会调用,中间的有 #可能不会调用,通过上例可以看到二者的值是完全一样的。 '''5.控制显示位数,可以理解为:Scale的值为一整形,在输出显示时,它将会被转化为一字符串,如1.2转化为1.2或1.2000都是可以的''' #属性digits是控制显示的数字位数,将上面的例子中的数据以8位形式显示,在最后一位会添加一个0 # -*- coding: cp936 -*- from Tkinter import * root = Tk() def printScale(text): print 'text = ',text print 'v = ',v.get() v = StringVar() Scale(root, from_ = 0, #设置最小值 to = 100.0, #设置最大值 resolution = 0.0001, #设置步距值 orient = HORIZONTAL, #设置水平方向 digits = 8, #设置显示的位数为8 variable = v, #绑定变量 command = printScale #设置回调函数 ).pack() print v.get() root.mainloop() '''6.设置Scale的标签属性label''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() Scale(root, from_ = 0, #设置最大值 to = 100.0, #设置最小值 orient = HORIZONTAL, #设置水平方向 label = 'choice:', #设置标签值 ).pack() root.mainloop() #由label设置的值会显示在水平Scale的上方,用于提示信息 '''7.设置/取得Scale的值''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() sl = Scale(root) sl.set(50) #将Scale的值设置为50 print sl.get() #打印当前的Scale的值 sl.pack() root.mainloop() #slider的位置位于了中间,sl.set(50)起作用了,打印值为50。 Tkinter教程之Spinbox篇 (2007-10-01 18:48) '''Tkinter教程之Spinbox篇''' #与Entry类似,但可以指定输入范围值 '''1.创建一个Spinbox''' from Tkinter import * root = Tk() Spinbox(root).pack() root.mainloop() #只是创建了一个Spinbox,其它的什么也做不了,与Scale不同,Scale使用缺省值就可以控制 值的改变。 '''2.设置Spinbox的最大、最小值和步距值''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() Spinbox(root, from_ = 0, #设置最小值 to = 100, #设置最大值 increment = 5 #设置增量值为5,这个与Scale的resolution意思相同 ).pack() root.mainloop() '''3.设置Spinbox的值,设置属性values,设置此值后,每次更新值将使用values指定的值,''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() sb = Spinbox(root, values = (0,2,20,40,-1), increment = 2 ) sb.pack() # 打印当前的Spinbox的值,为一tuple print sb['values'] root.mainloop() #显示的第一个值为0,up按钮则为2,20,40,-1,不再是增2操作,它会使用tuple的索引递增,至到tuple的最后一个项时,将不再增加; #down按钮与up按钮恰好相反,它使用tuple的索引递减 '''4.Spinbox绑定变量 ''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() v = StringVar() sb = Spinbox(root, values = (0,2,20,40,-1), increment = 2, textvariable = v ) v.set(20) print v.get() sb.pack() # 打印当前的Spinbox的值,为一tuple root.mainloop() #上面的代码将变量v与sb绑定,并将Spinbox的初始值设置为20,运行程序,Spinbox的值显示为20,再点击up按钮,此时值变为40, #即tuple的下一个值,再看下面的代码,与这个不同的是设置的值不包含在tuple之内 # -*- coding: cp936 -*- from Tkinter import * root = Tk() v = StringVar() sb = Spinbox(root, values = (0,2,20,40,-1), increment = 2, textvariable = v ) v.set(200) print v.get() sb.pack() # 打印当前的Spinbox的值,为一tuple root.mainloop() #运行程序,显示的值为200,再次点击up按钮,显示的值为2,即虽然Spinbox能将值显示出来,但并不会将200添加到变量中,此时的 #索引值依旧为0,因为没有找到200的项。当点击up时,索引值变为1,即显示的值为2。 '''5.设置Spinbox的回调函数''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() def printSpin(): print 'Spinbox' sb = Spinbox(root, from_ = 0, #最小值 to = 10, #最大值 command = printSpin#回调函数 ) sb.pack() root.mainloop() #每次点击Spinbox按钮时就会调用printSpin函数,打印出'Spinbox'。与Scale不同的是:它不需要参数。 '''6.打印Spinbox的当前内容,是显示的值,不是values的值。''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() def printSpin(): # 使用get()方法来得到当前的显示值 print sb.get() sb = Spinbox(root, from_ = 0, #最小值 to = 10, #最大值 command = printSpin#回调函数 ) sb.pack() root.mainloop() #每次点击Spinbox按钮时就会调用printSpin函数,打印出Spinbox的当前值。 '''7.删除Spinbox指定位置的字符(这是个有问题的程序)''' #在回调函数中使用delete,Spinbox初始值为1234,点击up一次Spinbox的值变为235,再次点击变为36,再次点击变为7,但实际执行结果 #为第一次点击235,再次点击为234,以后所有的点击操作均为此值。不知为何。 # -*- coding: cp936 -*- from Tkinter import * root = Tk() def printSpin(): sb.delete(0) print sb.get() sb = Spinbox(root, from_ = 1234, #最小值 to = 9999, #最大值 increment = 1, command = printSpin#回调函数 ) sb.pack() root.mainloop() # 如果不使用回调函数,两次调用delete则可以正常,工作如下代码: # -*- coding: cp936 -*- from Tkinter import * root = Tk() sb = Spinbox(root, from_ = 1234, #最小值 to = 9999, #最大值 increment = 1 ) sb.delete(0) sb.delete(0) print sb.get() sb.pack() root.mainloop() #此程序正常,可以打印出正确结果'34' '''关于delete回调函数异常问题,又使用如下代码作了实验''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() def printSpin(): # 使用delete()方法删除指定索引的字符 sb.delete(0) print sb.get() sb = Spinbox(root, values = (1234,234,34,4), command = printSpin ) sb.pack() root.mainloop() #则这个程序点击up可以打印出34,再次点击则为空。 ''' 这个是可以工作的:①当前的值为1234,②点击up按钮时,程序调用回调函数printSpin将Spinbox的当 前值变为234;③Spinbox查找值为234的项,得到索引为1,即当前的索引值变为1,up还会将索引增1,即变为2,所有显示的值 为34,为了更好理解,用如下代码再次测试: ''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() def printSpin(): # 使用delete()方法删除指定索引的字符 sb.delete(0) print sb.get() sb = Spinbox(root, values = (1234567890,234567890,34567890,4567890,567890, 67890,7890,890,90,0), command = printSpin #回调函数 ) sb.pack() root.mainloop() #这个程序显示的依次是1234567890,34567890,567890,7890,90。 #还不了解内部工作原理,先这样理解吧,使用delete时注意可能会出现这样的问题。 '''8.在Spinbox指定位置插入文本''' #在每项后面添加.00表示精度,同样使用回调函数实现,代码如下: # -*- coding: cp936 -*- from Tkinter import * root = Tk() def printSpin(): # 使用get()方法来得到当前的显示值 sb.insert(END,'.00') print sb.get() sb = Spinbox(root, from_ = 1234, #最小值 to = 9999, #最大值 increment = 1, command = printSpin#回调函数 ) sb.pack() root.mainloop() #每次点击Spinbox按钮时就会调用printSpin函数,当前的显示值均添加了两个有数字\".00\"。这个与delete不同,倒是可以正确显示。 ''' delete所遇到的问题,insert真的就不会发生吗?再次对上面的代码进行测试,代码如下: ''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() def printSpin(): # 使用get()方法来得到当前的显示值 sb.insert(END,'0') print sb.get() sb = Spinbox(root, from_ = 1234, #最小值 to = 9999, #最大值 increment = 1, command = printSpin #回调函数 ) sb.pack() root.mainloop() #在每个项的后加一个0,即将值变为原来的10倍,则程序的输出结果为123450,99990,同样也出现了异常 #现象,第一个例子的中出现正确的情况纯粹是个偶然,在整数的后添加.00相当于没有对其值进行改变,故下次 #使用的值依旧没有变化。 Tkinter教程之Scrollbar篇 (2007-10-01 21:07) '''Tkinter教程之Scrollbar篇''' #Scrollbar(滚动条),可以单独使用,但最多的还是与其它控件(Listbox,Text,Canva等)结合使用 '''1.创建一个Scrollbar''' from Tkinter import * root = Tk() Scrollbar(root).pack() root.mainloop() #显示了一个Scrollbar,但什么也做不了,无法拖动slider。 from Tkinter import * root = Tk() sl = Scrollbar(root) sl.set(0.5,0) sl.pack() root.mainloop() '''2.通过set方法来设置slider的位置''' #使用水平滚动条,通过set将值设置为(0.5,1),即slider占整个Srollbar的一半 from Tkinter import * root = Tk() sl = Scrollbar(root,orient = HORIZONTAL) sl.set(0.5,1) sl.pack() root.mainloop() '''3.使用回调函数(不建议这样使用)''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() def scrollCall(moveto,pos): #如何得到两个参数:使用如下打印中的信息,可以看到解释器传给scrollCall函数的两个参数,一个为 #moveto,参考手册可以得知,它是当拖动slider时调用的函数;另一个参数为slider的当前位置,我们 #可以通过set函数来设置slider的位置,因此使用这个pos就可以完成控制slider的位置。 #print moveto,pos sl.set(pos,0) print sl.get() sl = Scrollbar(root,orient = HORIZONTAL,command = scrollCall) sl.pack() root.mainloop() #这样还有一个严重问题,只能对其进行拖动。对两个按钮及pagedwon/pageup的响应,由 于up按钮响应的为三个参数,故会出 #现异常。这个例子只是用来说明command属性是可用的,如果喜欢自己可以处理所有的消息,将scrollCall是否可以改为变参数函数? #对于不同的输入分别进行不同的处理。 '''4.单独使用还是比较少见,大部分应用还是与其它控件的绑定,以下是将一个Listbox与Scrollbar绑定的例子''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() lb = Listbox(root) sl = Scrollbar(root) sl.pack(side = RIGHT,fill = Y) #side指定Scrollbar为居右;fill指定填充满整个剩余区域,到WM在时候再详细介绍这几个属性。 #下面的这句是关键:指定Listbox的yscrollbar的回调函数为Scrollbar的set lb['yscrollcommand'] = sl.set for i in range(100): lb.insert(END,str(i)) #side指定Listbox为居左 lb.pack(side = LEFT) #下面的这句是关键:指定Scrollbar的command的回调函数是Listbar的yview sl['command'] = lb.yview root.mainloop() '''5.这样理解二者之间的关系:当Listbox改变时,Scrollbar调用set以改变slder的位置;当Scrollbar改变了slider的位置时,Listbox调用yview以显示新的list项,为了演示这两种关系先将yscrollcommad与scrollbar的set解除绑定,看看会有什么效果''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() lb = Listbox(root) sl = Scrollbar(root) sl.pack(side = RIGHT,fill = Y) #解除Listbox的yscrollcommand与Scrollbar的set绑定 #lb['yscrollcommand'] = sl.set for i in range(100): lb.insert(END,str(i)) #使用索引为50的元素可见 lb.see(50) lb.pack(side = LEFT) sl['command'] = lb.yview root.mainloop() #运行结果,Listbox显示了50项,即Listbox的视图已经到50了,但Scrollbar的slider 仍旧位于0处。也就是说Scroolbar没有收到set #的命令。即说明解除此绑定,Scrollbar将不再响应Listbox视图改变的消息。但仍可以使用Scrollbar的slider来移动Listbox的视图。 '''6.再测试一下,解除Scrollbar的command与Listbox的yview的关系,测试代码如下:''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() lb = Listbox(root) sl = Scrollbar(root) sl.pack(side = RIGHT,fill = Y) #下面的这句是关键:指定Listbox的yscrollbar的回调函数为Scrollbar的set lb['yscrollcommand'] = sl.set for i in range(100): lb.insert(END,str(i*100)) #使用索引为50的元素可见 lb.see(50) lb.pack(side = LEFT) #解除Scrollbar的command与Listbox的yview的关系 #sl['command'] = lb.yview root.mainloop() #运行程序,Scrollbar的slider已经到了50位置,也就是说Scrollbar响应了Listbox视图改变的消息,调用 了自己的set函数。 #进行操作:拖动slder或点击up/down按钮,Listbox的视图没有任何反应,即Listbox不会响应Scrollbar的消息了。 Tkinter教程之Menu篇 (2007-10-02 11:03) '''Tkinter教程之Menu篇''' '''1.创建一个简单的Menu''' #添加菜单hello和quit,将hello菜单与hello函数绑定;quit菜单与root.quit绑定 # -*- coding: cp936 -*- from Tkinter import * root = Tk() def hello(): print 'hello menu' menubar = Menu(root) #创建主菜单,每个菜单对应的回调函数都是hello for item in ['Python','PHP','CPP','C','Java','JavaScript','VBScript']: menubar.add_command(label = item,command = hello) #将root的menu属性设置为menubar root['menu'] = menubar root.mainloop() #这个菜单没有下拉菜单,仅包含两个菜单项 '''2.添加下拉菜单''' from Tkinter import * root = Tk() def hello(): print 'hello menu' menubar = Menu(root) filemenu = Menu(menubar,tearoff = 0) for item in ['Python','PHP','CPP','C','Java','JavaScript','VBScript']: filemenu.add_commad(label = item,command = hello) #将menubar的menu属性指定为filemenu,即filemenu为menubar的下拉菜单 menubar.add_cascade(label = 'Language',menu = filemenu) root['menu'] = menubar root.mainloop() '''3.向菜单中添加Checkbutton项''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() #每次打印出各个变量的当前值 def printItem(): print 'Python = ',vPython.get() print 'PHP = ',vPHP.get() print 'CPP = ',vCPP.get() print 'C = ',vC.get() print 'Java = ',vJava.get() print 'JavaScript = ',vJavaScript.get() print 'VBScript = ',vVBScript.get() menubar = Menu(root) vPython = StringVar() vPHP = StringVar() vCPP = StringVar() vC = StringVar() vJava = StringVar() vJavaScript = StringVar() vVBScript = StringVar() filemenu = Menu(menubar,tearoff = 0) for k,v in {'Python':vPython, 'PHP':vPHP, 'CPP':vCPP, 'C':vC, 'Java':vJava, 'JavaScript':vJavaScript, 'VBScript':vVBScript}.items(): #绑定变量与回调函数 filemenu.add_checkbutton(label = k,command = printItem,variable = v) #将menubar的menu属性指定为filemenu,即filemenu为menubar的下拉菜单 menubar.add_cascade(label = 'Language',menu = filemenu) root['menu'] = menubar root.mainloop() #程序运行,使用了Checkbutton,并通过printItem将每个Checkbutton在当前值打印出来。 '''4.向菜单 中添加Radiobutton项''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() menubar = Menu(root) vLang = StringVar() #每次打印出当前选中的语言 def printItem(): print 'vLang = ',vLang.get() filemenu = Menu(menubar,tearoff = 0) for k in ['Python','PHP','CPP','C','Java','JavaScript','VBScript']: #绑定变量与回调函数,指定的变量vLang将这几项划为一组 filemenu.add_radiobutton(label = k,command = printItem,variable = vLang) #将menubar的menu属性指定为filemenu,即filemenu为menubar的下拉菜单 menubar.add_cascade(label = 'Language',menu = filemenu) root['menu'] = menubar root.mainloop() #程序每次打印出当前选中的语言 #与Checkbutton不同的是,同一个组内只有一个处于选中状态。 '''5.向菜单中添加分隔符''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() menubar = Menu(root) #每次打印出当前选中的语言 def printItem(): print 'add_separator' filemenu = Menu(menubar,tearoff = 0) for k in ['Python','PHP','CPP','C','Java','JavaScript','VBScript']: filemenu.add_command(label = k,command = printItem) #将各个菜单项使用分隔符隔开 filemenu.add_separator() menubar.add_cascade(label = 'Language',menu = filemenu) root['menu'] = menubar root.mainloop() #分隔符将相关的菜单项进行分组,只是UI上的实现,程序上没有任何改变,它也不执行任何的命令 ''' 6.将以上的例5中的菜单改为右击弹出菜单''' #方法是通过绑定鼠标右键,每当点击时弹出这个菜单,去掉与root的关联 # -*- coding: cp936 -*- from Tkinter import * root = Tk() menubar = Menu(root) def printItem(): print 'popup menu' filemenu = Menu(menubar,tearoff = 0) for k in ['Python','PHP','CPP','C','Java','JavaScript','VBScript']: filemenu.add_command(label = k,command = printItem) filemenu.add_separator() menubar.add_cascade(label = 'Language',menu = filemenu) #此时就不要将root的menu设置为menubar了 #root['menu'] = menubar def popup(event): #显示菜单 menubar.post(event.x_root,event.y_root) #在这里相应鼠标的右键事件,右击时调用popup,此时与菜单绑定的是root,可以设置为其它的控件,在绑定的控件上右击就可以弹出菜单 root.bind(' #运行测试一个,可以看到各个菜单 项的功能都是可以使用的,所以弹出菜单与一般的菜单功能是一样的,只是弹出的方式不同而已。 ''' 7.以下的代码演示了菜单项的操作方法,包括添加各种菜单项,删除一个或多个菜单项''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() menubar = Menu(root) def printItem(): print 'add_separator' filemenu = Menu(menubar,tearoff = 0) for k in range(5): filemenu.add_command(label = str(k),command = printItem) menubar.add_cascade(label = 'Language',menu = filemenu) '''以下为向菜单中添加项的操作''' #在索引1添加一菜单command项 filemenu.insert_command(1,label = '1000',command = printItem) #在索引2添加一菜单checkbutton项 filemenu.insert_checkbutton(2,label = '2000',command = printItem) #在索引3添加一菜单radiobutton项 filemenu.insert_radiobutton(3,label = '3000',command = printItem) #将新添加的菜单项使用分隔符隔开 filemenu.insert_separator(1) filemenu.insert_separator(5) '''以下为删除菜单项的操作''' #删除索引6-9的菜单项 filemenu.delete(6,9) #删除索引为0的菜单项 filemenu.delete(0) root['menu'] = menubar root.mainloop() #分隔符将相关的菜单项进行分组,只是UI上的实现,程序上没有任何改变,它也不执行任何的命令 Tkinter教程之Menubutton篇 (2007-10-02 12:08) '''Tkinter教程之Menubutton篇''' '''这是一个过时了的控件,从Tk8.0开始将不再使用这个控件,取而代之的是Menu,这里介绍它是为了 兼容以前版本的Tk,能够知道有这个东东就可以了''' '''1.介绍一下Menubutton的常用 方法,可以看到与Menu的使用方法基本相同。''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() mbLang = Menubutton(root,text = 'Language') mbLang.menu = Menu(mbLang) #生成菜单项 for item in ['Python','PHP','CPP','C','Java','JavaScript','VBScript']: mbLang.menu.add_command(label = item) mbLang['menu'] = mbLang.menu mbLang.pack(side = LEFT) #分隔符将相关的菜单项进行分组,只是UI上的实现,程序上没有任何改变,它也不执行任何的命令 #添加向菜单中添加checkbutton项 mbOS = Menubutton(root,text = 'OS') mbOS.menu = Menu(mbOS) for item in ['Unix','Linux','Soloris','Windows']: mbOS.menu.add_checkbutton(label = item) mbOS['menu'] = mbOS.menu mbOS.pack(side = LEFT) #向菜单中添加radiobutton项 mbLinux = Menubutton(root,text = 'Linux') mbLinux.menu = Menu(mbLinux) for item in ['Redhat','Fedra','Suse','ubuntu','Debian']: mbLinux.menu.add_radiobutton(label = item) mbLinux['menu'] = mbLinux.menu mbLinux.pack(side = LEFT) #对菜单项进行操作 #向Language菜单中添加一项\"Ruby\",以分隔符分开 mbLang.menu.add_separator() mbLang.menu.add_command(label = 'Ruby') #向OS菜单中第二项添加\"FreeBSD\",以分隔符分开 mbOS.menu.insert_separator(2) mbOS.menu.insert_checkbutton(3,label = 'FreeBSD') mbOS.menu.insert_separator(4) #将Linux中的“Debian”删除 mbLinux.menu.delete(5) root.mainloop() #这个控件已经不提倡使用,取而代之的是Menu,使用这个比使用Menubutton更为方便。如果不是特别需要不要使用这个控件。 Tkinter教程之Message篇 (2007-10-02 18:00) '''Tkinter教程之Message篇''' #Message也是用来显示文本的,用法与Label基本一样 '''1..创建一个简单的Message''' from Tkinter import * root = Tk() Message(root,text = 'hello Message').pack() root.mainloop() #运行程序,可以看到Hello之后,Message显示在它的下一行,这也是Message的一个特性。Label没有。 '''2.如果不让它换行的话,指定足够大的宽度''' from Tkinter import * root = Tk() Message(root,text = 'hello Message',width = 60).pack() root.mainloop() #运行程序,可以看到Hello之后,Message显示在它的下一行,这也是Message的一个特性。Label没有。 '''3.使用aspect属性指定宽高比例''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() for i in range(10): Message(root,text = 'A'*i,aspect = 400).pack() root.mainloop() #默认情况向wider/height = 1.5,可以使用aspect属性,设置为4,即宽为高的4倍,可以显示10个'A' '''4.Message绑定变量''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() v = StringVar() v.set('000') for i in range(10): Message(root,text = 'A',textvariable = v).pack() #打印当前的v值,只要是其中的一个Message的值发生变化,则此v值就会改变。 print v.get() root.mainloop() #绑定变量v,虽然创建Message时使用了text来指定Message的值,绑定的变量优先级高,可以改变text #指定的值。 '''5.测试一下justify属性''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() for i in [LEFT,RIGHT,CENTER]: Message(root,text = 'ABC DEF GHI',justify = i).pack() root.mainloop() #显示的文本自动断行,上下行分别使用了左对齐,右对齐和居中对齐 Tkinter教程之OptionMenu篇 (2007-10-02 18:02) '''Tkinter教程之OptionMenu篇''' #OptionMenu为可选菜单,与Combox功能类似。 '''1.创建OptionMenu''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() v = StringVar(root) v.set('Python') om = OptionMenu(root,v,'Python','PHP','CPP','C','Java','JavaScript','VBScript') om.pack() root.mainloop() #显示的文本自动断行,上下行分别使用了左对齐,右对齐和居中对齐 # -*- coding: cp936 -*- from Tkinter import * root = Tk() v = StringVar(root) #创建一个OptionMenu控件 om = OptionMenu(root, v, 'Python', 'PHP', 'CPP', 'C', 'Java', 'JavaScript', 'VBScript' ) om.pack() root.mainloop() #OptionMenu的创建需要两个必要的参数,与当前值绑定的变量,通常为一StringVar类型;另一 #个是提供可选的内容列表,由OptionMenu的变参数指定。 '''2.设置OptionMenu的显示值''' #当OptionMenu与变量绑定后,直接使用变量赋值的方法即可改变当前的值 # -*- coding: cp936 -*- from Tkinter import * root = Tk() v = StringVar(root) v.set('VBScript') #创建一个OptionMenu控件 om = OptionMenu(root, v, 'Python', 'PHP', 'CPP', 'C', 'Java', 'JavaScript', 'VBScript' ) om.pack() print v.get() root.mainloop() #运行程序,OptionMenu默认值为\"VBScript\",打印出的数值也为\"VBScript\" #如果设置的值不包含在当前的列表中,会是什么结果?如下的代码使用\"Tkinter\"来测试 # -*- coding: cp936 -*- from Tkinter import * root = Tk() v = StringVar(root) v.set('Tkinter') #创建一个OptionMenu控件 om = OptionMenu(root, v, 'Python', 'PHP', 'CPP', 'C', 'Java', 'JavaScript', 'VBScript' ) om.pack() print v.get() root.mainloop() #程序依旧是默认值改变为Tkinter,打印结果也变为Tkinter,但Tkinter不会添加到OptionMenu的列表中,也就是说,当选择其它的选项时,Tkinter的值会丢失。 '''3.打印OptionMenu的值''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() v = StringVar(root) v.set('Tkinter') def printOption(event): print v.get() #创建一个OptionMenu控件 om = OptionMenu(root, v, 'Python', 'PHP', 'CPP', 'C', 'Java', 'JavaScript', 'VBScript' ) om.bind(' root.mainloop() #每次点击OptionMenu程序打印出上次选中的项值 '''使用list作为OptionMenu的选项''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() Lang = ['Python','PHP','CPP','C','Java','JavaScript','VBScript'] v = StringVar(root) v.set('Tkinter') def printOption(event): print v.get() #创建一个OptionMenu控件,使用了apply函数 om = apply(OptionMenu,(root,v) + tuple(Lang)) om.bind(' root.mainloop() Tkinter教程之Frame篇 (2007-10-02 20:58) '''Tkinter教程之Frame篇''' #Frame就是屏幕上的一块矩形区域,多是用来作为容器(container)来布局窗体。 '''1.创建Frame''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() #以不同的颜色区别各个frame for fm in ['red','blue','yellow','green','white','black']: #注意这个创建Frame的方法与其它创建控件的方法不同,第一个参数不是root Frame(height = 20,width = 400,bg = fm).pack() root.mainloop() #添加不同颜色的Frame,大小均为20*400 '''2.向Frame中添加Widget''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() fm = [] #以不同的颜色区别各个frame for color in ['red','blue']: #注意这个创建Frame的方法与其它创建控件的方法不同,第一个参数不是root fm.append(Frame(height = 200,width = 400,bg = color)) #向下面的Frame中添加一个Label Label(fm[1],text = 'Hello label').pack() fm[0].pack() fm[1].pack() root.mainloop() #Label被添加到下面的Frame中了,而不是root默认的最上方。 #大部分的方法来自gm,留到后面gm时再介绍 '''3.Tk8.4以后Frame又添加了一类LabelFrame,添加了Title的支持''' from Tkinter import * root = Tk() for lf in ['red','blue','yellow']: #可以使用text属性指定Frame的title LabelFrame(height = 200,width = 300,text = lf).pack() root.mainloop() Tkinter教程之PanedWindow (2007-10-02 21:00) '''Tkinter教程之PanedWindow''' #PaneWindow(面板)为一gm,用来管理子Widget '''1.向PanedWindow中添加Pane''' #使用add方法 # -*- coding: cp936 -*- from Tkinter import * root = Tk() panes = PanedWindow(orient = VERTICAL) panes.pack(fill = BOTH,expand = 1) for w in [Label,Button,Checkbutton,Radiobutton]: panes.add(w(panes,text = 'hello')) root.mainloop() #每个pane中创建一个widget '''2.删除PanedWindow指定的pane''' #使用forget/remove方法 # -*- coding: cp936 -*- from Tkinter import * root = Tk() ws = [] panes = PanedWindow(orient = VERTICAL) panes.pack(fill = BOTH,expand = 1) #创建四个pane for w in [Label,Button,Checkbutton,Radiobutton]: ws.append(w(panes,text = 'hello')) for w in ws: panes.add(w) #从panes中删除包含子Button的pane,使用remove与forget相同 panes.forget(ws[1]) #panes.remove(ws[1]) root.mainloop() #只有三个widget,Button已被删除。 '''3.在PanedWindow指定位置添加一个pane''' #使用paneconfig方法 # -*- coding: cp936 -*- from Tkinter import * root = Tk() ws = [] ps = PanedWindow(orient = VERTICAL) ps.pack(fill = BOTH,expand = 1) #创建四个pane for w in [Label,Button,Checkbutton,Radiobutton]: ws.append(w(ps,text = 'hello')) for w in ws: ps.add(w) #在0之后添加一个Lable,出错!!! #ps.after(ws[0],Label(ps,text = 'world')) #注意被添加的widget是第一个参数,after指定是位于那一个widget之后 #不要与after方法混淆了 ps.paneconfig(Label(ps,text = 'world'),after = ws[0]) root.mainloop() #这个widget主要也是用来做Container的,使用了大量的gm方法。 Tkinter教程之Toplevel篇 (2007-10-02 21:02) '''Tkinter教程之Toplevel篇''' #TopLevel与Frame类似,但它包含窗体属性(如Title) '''1.创建简单的Toplevel''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() tl = Toplevel() #为了区别root和tl,我们向tl中添加了一个Label Label(tl,text = 'hello label').pack() root.mainloop() #运行结果生成了两个窗体,一个是root启动的,另一个则是Toplevel创建的,它包含有一个label;关闭tl #则没有退出程序,Tk仍旧工作;若关闭Tk,整个Tk结束tl也结束,它不能单独存在。 '''2.设置Toplevel的属性''' #title设置标题 #geometry设置宽和高 # -*- coding: cp936 -*- from Tkinter import * root = Tk() tl = Toplevel() #设置tl的title tl.title('hello Toplevel') #设置tl在宽和高 tl.geometry('400x300') #为了区别root和tl,我们向tl中添加了一个Label Label(tl,text = 'hello label').pack() root.mainloop() '''3.使用Toplevel自己制作提示框''' # -*- coding: cp936 -*- from Tkinter import * root = Tk() mbYes,mbYesNo,mbYesNoCancel,mbYesNoAbort = 0,1,2,4 #定义一个消息对话框,依据传入的参数不同,弹出不同的提示信息 def MessageBox(): #没有使用使用参数 mbType = mbYesNo textShow = 'Yes' if mbType == mbYes: textShow = 'Yes' elif mbType == mbYesNo: textShow = 'YesNo' elif mbType == mbYesNoCancel: textShow = 'YesNoCancel' elif mbType == mbYesNoAbort: textShow = 'YesNoAbort' tl = Toplevel(height = 200,width = 400) Label(tl,text = textShow).pack() #由Button来启动这个消息框,因为它使用了空的回调函数,故MessageBox改为了无参数形式,使用了固定 #值mbYesNo Button(root,text = 'click me',command = MessageBox).pack() root.mainloop() Tkinter教程之Text篇(1) (2007-10-03 22:05) '''Tkinter教程之Text篇(1)''' '''1.创建第一个Text''' from Tkinter import * root = Tk() t = Text(root) t.pack() root.mainloop() #root中含有一Text控件,可以在这个控件内输入文本,可以使用Ctrl+C/V向Text内添加剪切板上的内容(文本),不接受Ctrl+Z执行操作 '''2.向Text中添加文本''' #insert方法添加文本内容 from Tkinter import * root = Tk() t = Text(root) #向第一行,第一列添加文本0123456789 t.insert(1.0,'0123456789') #向第一行第一列添加文本ABCDEFGHIJ t.insert(1.0,'ABCDEFGHIJ') t.pack() root.mainloop() #insert的第一个参数为索引;第二个为添加的内容 '''3.使用line.col索引添加内容''' #使用indexes来添加Text的内容 # -*- coding: cp936 -*- from Tkinter import * root = Tk() t = Text(root) # 向第一行,第一列添加文本0123456789 t.insert(1.0,'0123456789') t.insert('2.end','\\n') # 向第一行第一列添加文本ABCDEFGHIJ t.insert(2.5,'ABCDEFGHIJ') t.pack() root.mainloop() # 可以看到使用indexes时,如果其值超过了Text的buffer值,程序不会抛出异常,它会使用向给定值靠近。 '''mark是用来表示在Text中位置的一类符号''' '''4.使用内置的mark控制添加位置''' #演示了内置的mark:INSERT/CURRENT/END/SEL_FIRST/SEL_LAST的用法 # -*- coding: cp936 -*- from Tkinter import * root = Tk() t = Text(root) #向Text中添加10行文本 for i in range(1,10): t.insert(1.0,'0123456789\\n') #定义各个Button的回调函数,这些函数使用了内置的mark:INSERT/CURRENT/END/SEL_FIRST/SEL_LAST def insertText(): t.insert(INSERT,'jcodeer') def currentText(): t.insert(CURRENT,'jcodeer') def endText(): t.insert(END,'jcodeer') def selFirstText(): t.insert(SEL_FIRST,'jcodeer') def selLastText(): t.insert(SEL_LAST,'jcodeer') #INSERT Button(root, text = 'insert jcodeer at INSERT', command = insertText ).pack(fill = X) #CURRENT Button(root, text = 'insert jcodeer at CURRENT', command = insertText ).pack(fill = X) #END Button(root, text = 'insert jcodeer at END', command = endText ).pack(fill = X) #SEL_FIRST Button(root, text = 'insert jcodeer at SEL_FIRST', command = selFirstText ).pack(fill = X) #SEL_LAST Button(root, text = 'insert jcodeer at SEL_LAST', command = selLastText ).pack(fill = X) t.pack() root.mainloop() #几个内置的mark: #INSERT:光标的插入点 #CURRENT:鼠标的当前位置所对应的字符位置 #END:这个Text buffer的最后一个字符 #SEL_FIRST:选中文本域的第一个字符,如果没有选中区域则会引发异常 #SEL_LAST:选中文本域的最后一个字符,如果没有选中区域则会引发 异常 '''5.使用表达式来增强mark''' #表达式(expression)可以个性任何的Indexes,如下: ''' + count chars :前移count字符 - count chars :后移count字符 + count lines :前移count行 - count lines :后移count行 linestart:移动到行的开始 linesend:移动到行的结束 wordstart:移动到字的开始 wordend:移动到字的结束 ''' # 演示修饰符表达式的使用方法,如何与当前可用的indexes一起使用 # -*- coding: cp936 -*- from Tkinter import * root = Tk() t = Text() # 向第一行,第一列添加文本0123456789 for i in range(1,10): t.insert(1.0,'0123456789\\n') a = 'test_mark' def forwardChars(): # 直接连接字符串 # t.mark_set(a,CURRENT + '+ 5 chars') t.mark_set(a,CURRENT + '+5c') def backwardChars(): # t.mark_set(a,CURRENT + '- 5 chars') t.mark_set(a,CURRENT + '-5c') def forwardLines(): # t.mark_set(a,CURRENT + '+ 5 lines) t.mark_set(a,CURRENT + '+5l') def backwardLines(): # t.mark_set(a,CURRENT + '- 5 lines) t.mark_set(a,CURRENT + '-5l') def lineStart(): # 注意linestart前面的那个空格不可省略 t.mark_set(a,CURRENT + ' linestart') def lineEnd(): # 注意lineend前面的那个空格不可省略 t.mark_set(a,CURRENT + ' lineend') def wordStart(): # 移动到当前字的开始。 t.mark_set(a,CURRENT + ' wordstart') def wordend(): # 移动到当前字的结束 t.mark_set(a,CURRENT + ' wordend') # mark:test_mark默认值为CURRENT t.mark_set(a,CURRENT) Button(root,text = 'forward 5 chars',command = forwardChars).pack(fill = X) Button(root,text = 'backward 5 chars',command = backwardChars).pack(fill = X) Button(root,text = 'forward 5 lines',command = forwardLines).pack(fill = X) Button(root,text = 'backward 5 lines',command = backwardLines).pack(fill = X) Button(root,text = 'line start',command = lineStart).pack(fill = X) Button(root,text = 'line end',command = lineEnd).pack(fill = X) Button(root,text = 'word start',command = lineEnd).pack(fill = X) Button(root,text = 'word end',command = lineEnd).pack(fill = X) # 测试三个位置的不同,CURRENT可以得知是当前光标的位置;mark就表示mark的位置了,INSERT好像一植都在1.0处没有改变。 def insertText(): t.insert(INSERT,'insert') def currentText(): t.insert(CURRENT,'current') def markText(): t.insert(a,'mark') Button(root,text = 'insert jcodeer.cublog.cn',command = insertText).pack(fill = X) Button(root,text = 'current jcodeer.cublog.cn',command = currentText).pack(fill = X) Button(root,text = 'mark jcodeer.cublog.cn',command = markText).pack(fill = X) t.pack() root.mainloop() Tkinter教程之Text篇(2) (2007-10-04 09:53) '''Tkinter教程之Text篇(2)''' '''6.使用tag来指定文本的属性''' #创建一个指定背景颜色的TAG # -*- coding: cp936 -*- from Tkinter import * root = Tk() t = Text(root) # 创建一个TAG,其前景色为红色 t.tag_config('a',foreground = 'red') # 使用TAG 'a'来指定文本属性 t.insert(1.0,'0123456789','a') t.pack() root.mainloop() #结果是文本颜色改变为红色了 '''7.同时使用两个文本指定同一个属性''' #没有特别设置的话,最后创建的那个会覆盖掉其它所有的设置 # -*- coding: cp936 -*- from Tkinter import * root = Tk() t = Text(root) # 创建一个TAG,其前景色为红色 t.tag_config('a',foreground = 'red') t.tag_config('b',foreground = 'blue') # 使用TAG 'a'来指定文本属性 t.insert(1.0,'0123456789',('b','a')) t.pack() root.mainloop() # 结果是文本的颜色不是按照insert给定的顺序来设置,而是按照tag的创建顺序来设置的。 '''8.控制tag的级别''' #使用tag_lower/tag_raise来降低或提高tag的级别 # -*- coding: cp936 -*- from Tkinter import * root = Tk() t = Text(root) # 创建一个TAG,其前景色为红色 t.tag_config('a',foreground = 'red') t.tag_config('b',foreground = 'blue') # 使用tag_lower来降低b的级别 t.tag_lower('b') # 使用TAG 'a'来指定文本属性 t.insert(1.0,'0123456789',('b','a')) t.pack() root.mainloop() # 结果:文本内容颜色变为了红色,蓝色的作用级别小于红色了,即使是先创建了红色。 '''9.对文本块添加tag''' # tag_add方法的使用 # -*- coding: cp936 -*- from Tkinter import * root = Tk() t = Text(root) # 创建一个TAG,其前景色为蓝色 t.tag_config('b',foreground = 'blue') # 使用tag_lower来控制tag的级别 t.tag_lower('b') # 使用TAG 'a'来指定文本属性 for i in range(10): t.insert(1.0,'0123456789\\n') t.tag_add('b','2.5','2.end') t.pack() root.mainloop() # 先向Text中添加了10行文本,创建一tag,将第2行第6列至第二行行尾使用使用此tag '''10.使用自定义mark对文本块添加tag''' # -*- coding: cp936 -*- # tag_add方法的使用 from Tkinter import * root = Tk() t = Text(root) # 创建一个TAG,其前景色为蓝色 t.tag_config('b',foreground = 'blue') # 使用tag_lower来控制tag的级别 t.tag_lower('b') # 使用TAG 'a'来指定文本属性 for i in range(10): t.insert(1.0,'0123456789\\n') # 自定义两个mark,并使用它们来指定添加tag的文本块 t.mark_set('ab','3.1') t.mark_set('cd',END) t.tag_add('b','ab','cd') t.pack() root.mainloop() # 先向Text中添加了10行文本,创建两个mark('ab'和'cd'),将使用这两个tag指定文本的文本块使用此tag '''11.使用indexes获得Text中的内容''' # -*- coding: cp936 -*- # 分别使用内置的indexes和自定义mark来获取文本 # get方法的使用 from Tkinter import * root = Tk() t = Text(root) for i in range(10): t.insert(1.0,'0123456789\\n') # 获得1.0-2.3的文本 print t.get('1.0','2.3') # 自定义两个mark,并使用它们来获得文本块 t.mark_set('ab','3.1') t.mark_set('cd',END) print t.get('ab','cd') t.pack() root.mainloop() '''12.测试delete对tag的影响''' # -*- coding: cp936 -*- # delete方法不会对tag造成影响,也就是说删除文本与tag没有任何关系 from Tkinter import * root = Tk() t = Text(root) # 创建一个TAG,其前景色为蓝色 t.tag_config('b',foreground = 'blue') for i in range(10): t.insert(1.0,'0123456789\\n') # 自定义两个mark,并使用它们来指定添加tag的文本块 t.mark_set('ab','3.1') t.mark_set('cd',END) t.tag_add('b','ab','cd') # 删除(1.0 - 4.0)的文本 t.delete('1.0','4.0') t.pack() root.mainloop() # (1.0-4.0)的文本全部初始删除了,剩余的文本全部以蓝色显示,即还保留tag的属性 '''13.使用tag_delete对文本属性的影响''' # -*- coding: cp936 -*- # 使用tag_delete方法操作tag from Tkinter import * root = Tk() t = Text(root) # 创建一个TAG,其前景色为蓝色 t.tag_config('b',foreground = 'blue') for i in range(10): t.insert(1.0,'0123456789\\n') # 自定义两个mark,并使用它们来指定添加tag的文本块 t.mark_set('ab','3.1') t.mark_set('cd',END) t.tag_add('b','ab','cd') # 删除tag 'b',注意这个操作是在tag_add之后进行的。 t.tag_delete('b') t.pack() root.mainloop() # 结果所有的文本没有了tag('b')属性,即tag_delete会清除所有与此tag相关的属性,不论是之前还是之后 Tkinter教程之Text篇(3) (2007-10-04 11:29) '''Tkinter教程之Text篇(3)''' '''14.自定义tag的两个内置属性''''' #tag.first:tag之前插入文本,此文本不包含在这个tag中 #tag.last:tag之后插入文本,此文本包含在这个tag中 # -*- coding: cp936 -*- # 使用tag的内置属性来插入文本 from Tkinter import * root = Tk() t = Text(root) # 创建一个TAG,其前景色为蓝色 t.tag_config('b',foreground = 'blue') for i in range(10): t.insert(1.0,'0123456789\\n') # 自定义两个mark,并使用它们来指定添加tag的文本块 t.mark_set('ab','3.1') t.mark_set('cd',END) t.tag_add('b','ab','cd') # 删除tag 'b',注意这个操作是在tag_add之后进行的。 # 在tag('b')之前插入'first' t.insert('b.first','first') # 在tag('b')之后插入'last' t.insert('b.last','last') t.pack() root.mainloop() # 注意:first没有使用tag('b')属性,last使用了tag('b')属性 '''15.在Text中创建按钮''' # -*- coding: cp936 -*- # 使用window_create在Text内创建一widget from Tkinter import * root = Tk() t = Text(root) for i in range(10): t.insert(1.0,'0123456789\\n') def printText(): print 'buttin in text' bt = Button(t,text = 'button',command = printText) # 在Text内创建一个按钮 t.window_create('2.0',window = bt) # 没有调用pack() # bt.pack() t.pack() root.mainloop() # 注意:使用window_create,而不是使用insert('2.0',bt);pack()也不用调用; # 点击这个按钮,打印出'button in text',证明这个按钮是可以正常工作的。 '''16.在Text中创建一个图像(未实现)''' # -*- coding: cp936 -*- # 使用window_create在Text内创建一widget from Tkinter import * root = Tk() t = Text(root) for i in range(10): t.insert(1.0,'0123456789\\n') # 分别使用BitmapImage和PhotoImage进行测试,均没有显示出图像??? #bm = BitmapImage('gray75') bm = PhotoImage('c:\\\\python.gif') # 在Text内创建一个图像 t.image_create('2.0',image = bm) print t.image_names() # 打印的图像名称都是正确的 t.pack() root.mainloop() # 按照手册中的说明未实现这种效果,原因不知。 '''17.绑定tag与事件''' # -*- coding: cp936 -*- # 使用tag_bind方法 from Tkinter import * root = Tk() t = Text(root) for i in range(10): t.insert(1.0,'0123456789\\n') # 创建一个tag t.tag_config('a',foreground = 'blue',underline = 1) # Enter的回调函数 def enterTag(event): print 'Enter event' # 绑定tag('a')与事件(' t.insert(2.0,'Enter event\\n','a') t.pack() root.mainloop() # 注意:使用tag_bind绑定tag与事件,当此事件在tag上发生时便就会调用这个tag的回调函数 # 因为使用了Enter事件,此事件含有一个参数,故将enterTag加了一个参数,程序中不使用此参数 '''18.使用edit_xxx实现编辑常用功能(未实现)''' # -*- coding: cp936 -*- # 使用edit_xxx函数实现编辑常用功能 from Tkinter import * root = Tk() t = Text(root) for i in range(10): t.insert(1.0,'0123456789\\n') t.pack() # 定义回调函数 # 撤消回调函数 def undoText(): t.edit_undo() # 插入文本函数 def insertText(): t.insert(1.0,'insert text') Button(root,text = 'undo',command = undoText).pack(fill = X) Button(root,text = 'insert text',command = insertText).pack(fill = X) root.mainloop() # 这个edit_undo方法也是不起作用,不知为何??? 来源网址 http://blog.chinaunix.net/space.php?uid=199788&do=blog&id=99387 因篇幅问题不能全部显示,请点此查看更多更全内容