Tkinter教程

 

      这系列教程完全以代码的形式来写的,目标是:读者看代码和注释就可以理解代码的意思。但这里的读者需要具备的几项技能:

  1. 熟悉python语言的基础,如果还没有,先看一下python的教程吧,英文官方(http://docs.python.org/tut/tut.html);
  2. 对界面编程有一定的了解,知道基本的概念就可以了;
  3. 对Tk有兴趣,别以为她是已经过时的技术,如果丧失了学习的兴趣,那肯定无法完成了;
  4. 不要以Ctrl+C/Ctrl+V的方式使用本教程(虽然它可以这样直接运行),自己输入,你会发现自己原来也会犯这样的错误;
  5. 安装了python2.5且确认安装了Tkinter模块(默认就安装了,如果你没有强制的把它去掉的话),下载python2.5(http://www.python.org/download/);
  6. 如果在阅读教程中有不明白的,不要强迫自己,直接跳过去,继续下一个内容。

Tkinter教程系列教程的特点:
 

  1. 他不是一本经过文字润色的文章,全部是代码,作者在必要的时候使用注释来解释;
  2. 以组件为章节进行介绍,每个组件又分为不同的例子,各个例子可以单独使用,分别使用序号标注;
  3. 各个例子的使用“注释+序号”的格式表示开始,下一个例子的开始为上一个例子的结束;
  4. 全部使用结构化编程(SP),没有面向对象的概念(OO);
  5. 基本上包含了TKinter的所有的控件,根据每个控件的使用方法,选择性的介绍了其属性和方法,没有全部介绍,全部的介绍查看Tkinter的官方参考(http://www.pythonware.com/library/tkinter/introduction/);
  6. 例子不是百分百的完美,甚至有的例子没有按照Tkinter参考的描述完成,原因由于作者没有看懂:(
  7. 参考书籍:http://www.pythonware.com/library/tkinter/introduction/,如有冲突以Tkinter参考为准

最后祝各位Tk一路快乐!

 

 

 

 

 


 

Label

#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中的位置

''

Button(1)

#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("<Return>",cb2)
b3 = Button(root,text = 'Button3',command = cb3)
b1.pack()
b2.pack()
b3.pack()

b2.focus_set()
root.mainloop()
'''
上例中使用了bind方法,它建立事件与回调函数(响应函数)之间的关系,每当产生<Enter>事件
后,程序便自动的调用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("<Return>",printEventInfo)
b.pack()
b.focus_set()
root.mainloop()   

'''
犯了个错误,将<Return>写成<Enter>了,结果是:当鼠标进入Button区域后,事件printEventInfo
被调用。程序打印出了event的信息。
'''

Button(2)

# 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显示的文本也随之变化
'''

Entry

#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相同,不再举例。

CheckButton

#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

RadioButton

#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表示按钮的弹起或按下两种状态

Listbox

#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('<Double-Button-1>',printList)
for i in range(10):
    lb.insert(END,str(i*100))
lb.pack()
root.mainloop()

#
还有一个比较实用的功能没有介绍:滚动条的添加,留到后面介绍Scrollbar的时候再一并介绍

Scale

'''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。

 

Spinbox

'''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相当于没有对其值进行改变,故下次
#使用的值依旧没有变化。

 Scrollbar

'''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的消息了。

Menu

'''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('<Button-3>',popup)
root.mainloop()
#运行测试一个,可以看到各个菜单 项的功能都是可以使用的,所以弹出菜单与一般的菜单功能是一样的,只是弹出的方式不同而已。

''' 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上的实现,程序上没有任何改变,它也不执行任何的命令
 

Menubutton

'''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更为方便。如果不是特别需要不要使用这个控件。
 

Message

'''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()
#显示的文本自动断行,上下行分别使用了左对齐,右对齐和居中对齐
 

OptionMenu

'''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('<Button-1>',printOption)
om.pack()

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('<Button-1>',printOption)
om.pack()

root.mainloop()

Frame

 

'''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()
 

PanedWindow

'''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方法。

Toplevel

'''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()
 

Text (1)

'''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()
 

Text (2)

'''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相关的属性,不论是之前还是之后

Text (3)

'''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')与事件('<Enter>')
t.tag_bind('a','<Enter>',enterTag)
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方法也是不起作用,不知为何???

Canvas(1)

'''Tkinter教程之Canvas篇(1)'''
# 提供可以用来进行绘图的Container,支持基本的几何元素,使用Canvas进行绘图时,所有的操作都是通过Canvas,不是通过它的元素
# 元素的表示可以使用handle或tag。

'''1.第一个Canvas程序'''
# -*- coding: cp936 -*-
# 指定画布的颜色为白色
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
cv.pack()
root.mainloop()
# 为明显起见,将背景色设置为白色,用以区别root

'''2.创建一个item'''
# -*- coding: cp936 -*-
# 创建一个矩形,指定画布的颜色为白色
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
# 创建一个矩形,坐标为(10,10,110,110)
cv.create_rectangle(10,10,110,110)
cv.pack()
root.mainloop()
# 为明显起见,将背景色设置为白色,用以区别root
'''3.指定item的填充色'''
# -*- coding: cp936 -*-
# 创建一个矩形,指定画布的背景色为白色
# 使用属性fill设置它的填充颜色

from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
cv.create_rectangle(10,10,110,110,fill = 'red')
cv.pack()
root.mainloop()
# 指定矩形的填充色为红色
'''4.指定item的边框颜色'''
# -*- coding: cp936 -*-
# 创建一个矩形,指定画布的背景色为白色
# 使用属性outline设置它的边框颜色

from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
cv.create_rectangle(10,10,110,110,outline = 'red')
cv.pack()
root.mainloop()
# 指定矩形的边框颜色为红色
'''5.指定边框的宽度'''
# -*- coding: cp936 -*-
# 指定画布的背景色为白色
# 使用属性width指定线的宽度

from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
cv.create_rectangle(10,10,110,110,outline = 'red',width = 5)
cv.pack()
root.mainloop()
# 指定矩形的边框颜色为红色,设置线宽为5,注意与Canvas的width是不同的。
'''6.画虚线'''
# -*- coding: cp936 -*-
# 指定画布的背景色为白色
# 使用属性dash
,这个值只能为奇数
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
cv.create_rectangle(10,10,110,110,
                    outline = 'red',
                    dash = 10,
                    fill = 'green')
cv.pack()
root.mainloop()
# 指定矩形的边框颜色为红色,画虚线
'''7.使用画刷填充'''
# -*- coding: cp936 -*-
# 指定画布的背景色为白色
# 使用属性stipple

from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
cv.create_rectangle(10,10,110,110,
                    outline = 'red',
                    stipple = 'gray12',
                    fill = 'green')
cv.pack()
root.mainloop()
# 指定矩形的边框颜色为红色,自定义画刷
'''8.修改item的坐标'''
# -*- coding: cp936 -*-
# 指定画布的背景色为白色
# 使用Canvas的方法来重新设置item的坐标

from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
rt = cv.create_rectangle(10,10,110,110,
                    outline = 'red',
                    stipple = 'gray12',
                    fill = 'green')
cv.pack()
# 重新设置rt的坐标(相当于移动一个item)
cv
.coords(rt,(40,40,80,80))
root.mainloop()
# 动态修改item的坐标


 

Canvas(2)

'''Tkinter教程之Canvas篇(2)'''
'''9.创建item的tags'''
# -*- coding: cp936 -*-
# 使用属性tags设置item的tag
# 使用Canvas的方法gettags获取指定item的tags

from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
# 使用tags指定一个tag('r1')
rt = cv.create_rectangle(10,10,110,110,
                         tags = 'r1'
                         )
cv.pack()

print cv.gettags(rt)
# 使用tags属性指定多个tags,即重新设置tags的属性
cv
.itemconfig(rt,tags = ('r2','r3','r4'))
print cv.gettags(rt)
root.mainloop()
# 动态修改item的坐标
'''10.多个item使用同一个tag'''
# -*- coding: cp936 -*-
# 多个控件使用同一个tag
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
# 使用tags指定一个tag('r1')
rt = cv.create_rectangle(10,10,110,110,
                         tags = ('r1','r2','r3')
                         )
cv.pack()

cv.create_rectangle(20,20,80,80,tags = 'r3')
print cv.find_withtag('r3')
root.mainloop()
# 动态修改item的坐标
#fid_withtag返回所有与tag绑定的item。

'''11.通过tag来访问item'''
# -*- coding: cp936 -*-
# 得到了tag值也就得到了这个item,可以对这个item进行相关的设置。
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
# 使用tags指定一个tag('r1')
rt = cv.create_rectangle(10,10,110,110,
                         tags = ('r1','r2','r3')
                         )
cv.pack()

cv.create_rectangle(20,20,80,80,tags = 'r3')
# 将所有与tag('r3')绑定的item边框颜色设置为蓝色
for item in cv.find_withtag('r3'):
    cv.itemconfig(item,outline = 'blue')
root.mainloop()
# 动态修改与tag('r3')绑定的item边框颜色
'''13.向其它item添加tag'''
# -*- coding: cp936 -*-
# 使用addtag_来向上一个或下一个item添加tag
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
# 创建三个rectangle
rt1
= cv.create_rectangle(
    10,10,110,110,
    tags = ('r1','r2','r3'))
rt2 = cv.create_rectangle(
    20,20,80,80,
    tags = ('s1','s2','s3'))
rt3 = cv.create_rectangle(
    30,30,70,70,
    tags = ('y1','y2','y3'))
# 向rt2的上一个item添加r4
cv
.addtag_above('r4',rt2)
# 向rt2的下一个item添加r5
cv
.addtag_below('r5',rt2)

for item in [rt1,rt2,rt3]:
    print cv.gettags(item)

cv.pack()
root.mainloop()
#Canvas使用了stack的技术,新创建的item总是位于前一个创建的item之上,故调用above时,它会查找rt2上面的item为rt3,故rt3中添加了tag('r4'),同样add_below会查找下面的item。
'''14.返回其它item'''
# -*- coding: cp936 -*-
# 使用find_xxx查找上一个或下一个item
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
# 创建三个rectangle
rt1
= cv.create_rectangle(
    10,10,110,110,
    tags = ('r1','r2','r3'))
rt2 = cv.create_rectangle(
    20,20,80,80,
    tags = ('s1','s2','s3'))
rt3 = cv.create_rectangle(
    30,30,70,70,
    tags = ('y1','y2','y3'))
# 查找rt2的上一个item,并将其边框颜色设置为红色
cv
.itemconfig(cv.find_above(rt2),outline = 'red')
# 查找rt2的下一个item,并将其边框颜色设置为绿色
cv
.itemconfig(cv.find_below(rt2),outline = 'green')

cv.pack()
root.mainloop()
#Canvas使用了stack的技术,新创建的item总是位于前一个创建的item之上,故调用above时,它会查找rt2上面的item为rt3,故rt3中边框颜色设置为红色,同样add_below会查找下面的item。

Canvas(3)

'''Tkinter教程之Canvas篇(3)'''
'''16.移动item'''
# -*- coding: cp936 -*-
# move指定x,y在偏移量
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
# 创建两个同样的rectangle,比较移动前后的不同
rt1
= cv.create_rectangle(
    10,10,110,110,
    tags = ('r1','r2','r3'))
cv.create_rectangle(
    10,10,110,110,
    tags = ('r1','r2','r3'))
# 移动rt1
cv
.move(rt1,20,-10)
cv.pack()
root.mainloop()
# move可以指定x,y在相对偏移量,可以为负值
'''17.删除item'''
# -*- coding: cp936 -*-
# delete删除给定的item
from Tkinter import *
root = Tk()
cv = Canvas(root,bg = 'white')
# 创建两个rectangle
rt1
= cv.create_rectangle(
    10,10,110,110,
    tags = ('r1','r2','r3'))
r2 = cv.create_rectangle(
    20,20,110,110,
    tags = ('s1','s2','s3'))
# 使用id删除rt1
cv
.delete(rt1)
# 使用tag删除r2
cv
.delete('s1')

cv.pack()
root.mainloop()
# 两种方法删除item(id/tag)
'''18.缩放item'''
# -*- coding: cp936 -*-
# scale缩放item,计算公式:(coords - offset)*scale + offset
from Tkinter import *
root = Tk()
cv = Canvas(root,bg = 'white')
# 创建两个rectangle
rt1
= cv.create_rectangle(
    10,10,110,110,
    tags = ('r1','r2','r3'))
# 将y坐标放大为原来的2位,x坐标值不变
cv
.scale(rt1,0,0,1,2)
cv.pack()
root.mainloop()
# scale的参数为(self,xoffset,yoffset,xscale,yscale)
'''19.绑定item与event'''
# -*- coding: cp936 -*-
# 使用tag_bind来绑定item与事件
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
# 创建三个rectangle
rt1
= cv.create_rectangle(
    10,10,110,110,
    width = 8,
    tags = ('r1','r2','r3'))
def printRect(event):
    print 'rectangle'
# 绑定item与事件
cv
.tag_bind('r1','<Button-1>',printRect)
cv.pack()
root.mainloop()
# 只有点击到矩形的边框时才会触发事件
'''20.添加绑定事件'''
# -*- coding: cp936 -*-
# 使用tag_bind来绑定item与事件,与参考上测试结果不一致。
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
# 创建三个rectangle
rt1
= cv.create_rectangle(
    10,10,110,110,
    width = 8,
    tags = ('r1','r2','r3'))
def printRect(event):
    print 'rectangle'
def printLine(event):
    print 'line'
# 绑定item与左键事件
cv
.tag_bind('r1','<Button-1>',printRect)
# 绑定item与右键事件
cv
.tag_bind('r1','<Button-3>',printLine)
cv.pack()
root.mainloop()
# 只有点击到矩形的边框时才会触发事件,不使用add参数,默认就是向这个item添加一个处理函数,它不会替换原来的事件函数,例子结果:既响应左键又响应右键
'''21.绑定新的item与现有的tags'''
# -*- coding: cp936 -*-
# 使用tag_bind来绑定item与事件,测试结果与参考上的说法不一致
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
# 创建三个rectangle
rt1
= cv.create_rectangle(
    10,10,110,110,
    width = 8,
    tags = ('r1','r2','r3'))
def printRect(event):
    print 'rectangle'
def printLine(event):
    print 'line'
# 绑定item与左键事件
cv
.tag_bind('r1','<Button-1>',printRect)
# 绑定item与右键事件
cv
.tag_bind('r1','<Button-3>',printLine)
# 创建一个line,并将其tags设置为'r1'
cv.create_line(10,200,100,200,width = 5,tags = 'r1')
cv.pack()
root.mainloop()
# 将事件与tag('r1')绑定后,创建新的item并指定已绑定事件的tag,新创建的item同样也与事件绑定,这个与参考上的说法也不一致

Canvas(4)

'''Tkinter教程之Canvas(4)篇'''
'''22.绘制弧形'''
# -*- coding: cp936 -*-
# 创建一个ARC
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
cv.create_arc((10,10,110,110),)
cv.pack()
root.mainloop()
# 使用默认参数创建一个ARC,结果为90度的扇形
'''23.设置弧形的样式'''
# -*- coding: cp936 -*-
# 创建create_arc.
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
d = {1:PIESLICE,2:CHORD,3:ARC}
for i in d:
    cv.create_arc((10,10 + 60*i,110,110 + 60*i),style = d[i])
    print i,d[i],
cv.pack()
root.mainloop()
# 使用三种样式,分别创建了扇形、弓形和弧形
'''24.设置弧形的角度'''
# -*- coding: cp936 -*-
# 使用start/extent指定起始角度与偏移角度
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
d = {1:PIESLICE,2:CHORD,3:ARC}
for i in d:
    cv.create_arc(
        (10,10 + 60*i,110,110 + 60*i),
        style = d[i], #指定样式
        start
= 30, #指定起始角度
        extent
= 30 #指定角度偏移量
       
)
cv.pack()
root.mainloop()
# 使用三种样式,start指定起始角度;extent指定角度偏移
'''25.绘制位图'''
# -*- coding: cp936 -*-
# 使用bitmap创建位图create_bitmap
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
d = {1:'error',2:'info',3:'question',4:'hourglass'}
for i in d:
    cv.create_bitmap((20*i,20*i),bitmap = d[i])
cv.pack()
root.mainloop()
# 使用bitmap属性来指定位图的名称,这个函数的第一个参数为一个点(x,y)指定位图存放位置的左上位置。
'''26.绘制GIF图像'''
# -*- coding: cp936 -*-
# 创建gif图像create_image
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
img = PhotoImage(file = 'c:\\python.gif')
cv.create_image((150,150),image = img)
cv.pack()
root.mainloop()
# 先使用PhotoImage创建GIF图像,再将image属性来设置为新创建的img
'''27.绘制直线'''
# -*- coding: cp936 -*-
# 创建带箭头的直线create_line
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
d = [(0,'none'),(1,'first'),(2,'last'),(3,'both')]
for i in d:
    cv.create_line(
        (10,10 + i[0]*20,110,110+ i[0] * 20), # 设置直线的起始、终点
        arrow
= i[1], # 设置直线是否使用箭头
        arrowshape
= '40 40 10' # 设置箭头的形状(填充长度,箭头长度,箭头宽度
       
)
cv.pack()
root.mainloop()
# 使用arrow属性来控制是否显示箭头
'''28.直线的joinstyle属性'''
# -*- coding: cp936 -*-
# 创建直线,使用joinstyle属性
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
d = [(0,'none','bevel'),(1,'first','miter'),(2,'last','round'),(3,'both','round')]
for i in d:
    cv.create_line(
        (10,10 + i[0]*20,110,110+ i[0] * 20), # 设置直线的起始、终点
        arrow
= i[1], # 设置直线是否使用箭头
        arrowshape
= '8 10 3', # 设置箭头的形状(填充长度,箭头长度,箭头宽度
        joinstyle
= i[2],
        )
cv.pack()
root.mainloop()
# 将直线的属性joinstyle分别设置为bevel/miter/round,测试其效果。
'''29.绘制椭圆'''
# -*- coding: cp936 -*-
# 绘制椭圆,使用create_oval属性
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
# 创建一个长200,宽100的椭圆
cv
.create_oval((10,10,210,110),fill = 'red')
cv.pack()
root.mainloop()
# 指定椭圆的长和宽,圆是长和宽相等的特殊情况。
'''30.创建多边形'''
# -*- coding: cp936 -*-
# 创建多边形(三角形)
from Tkinter import *
root = Tk()
# 绘制一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
# 创建一个直角三角形
cv
.create_polygon((10,10,10,200,100,200),fill = 'red')
cv.pack()
root.mainloop()
# 指定三个点的坐标,三个点坐标必须满足三角形的定义。
'''31.修饰图形'''
# -*- coding: cp936 -*-
# 创建多边形create_ploygon(三角形)
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
# 创建一个直角三角形
cv
.create_polygon((10,10,10,200,100,200),
                  #smooth = True, # 平滑处理,但未找到控制此参数的项
                  splinesteps
= 0, # 不明白是控制什么的???
                 
)
cv.pack()
root.mainloop()
# smooth/splinesteps用来修改绘制的图形,不明白这两个参数还有其它什么作用。
'''32.绘制文字'''
# -*- coding: cp936 -*-
# 使用文字create_text
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
# 创建一个文字对象,默认设置为居中对齐
cv
.create_text((10,10),text = 'Hello Text',
               anchor = W
               
)
cv.pack()
root.mainloop()
# 使用anchor控制文字的位置,使用justify控制对齐方式
'''33.选中文字'''
# -*- coding: cp936 -*-
# 使用文字create_text
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
# 创建一个文字对象,默认设置为居中对齐
txt
= cv.create_text((10,10),text = 'Hello Text',
               anchor = W
              
)
# 设置文本的选中起始位置
cv
.select_from(txt,2)
# 设置文本的选中结束位置
cv
.select_to(txt,5)

cv.pack()
root.mainloop()
# 使用anchor控制文字的位置,使用justify控制对齐方式
'''34.创建组件'''
# -*- coding: cp936 -*-
# 使用子组件create_window
from Tkinter import *
root = Tk()
# 创建一个Canvas,设置其背景色为白色
cv
= Canvas(root,bg = 'white')
# 创建一个Button对象,默认设置为居中对齐
def printWindow():
    print 'window'
bt = Button(cv,text = 'ClickMe',command = printWindow)
#修改button在canvas上的对齐方式
cv
.create_window((10,10),window = bt,anchor = W)
# 新创建的line对象与button有重叠
cv
.create_line(10,10,20,20)
# 新创建的line不在button之上,即没有重叠
cv
.create_line(30,30,100,100)
cv.pack()
root.mainloop()
# 使用anchor组件在Canvas上的位置,默认情况下为居中对齐,这样使用后其它的item将不能再使用button战胜的那块区域

Pack

'''Tkinter教程之Pack篇'''
#Pack为一布局管理器,可将它视为一个弹性的容器
'''1.一个空的widget'''
#不使用pack
#
-*- coding: cp936 -*-
from Tkinter import *
root = Tk()
# 查看当前root下的子组件,解释器没有报异常,说明Pack已创建,并可以使用,此时的输出为空,即root没有任何子组件。
print root.pack_slaves()
# 向root中pack一个Label
Label
(root,text = 'pack').pack()
# 再次打印出root的子组件,可以看到已经包含一个组件,即刚才创建的Label,说明Label调用pack()是将自己加入到了root中。
print root.pack_slaves()
root.mainloop()
# pack_salves打印当前组件包拥有的子组件,通过这个函数可以查看各个组件是否有包含关系。
'''2.root与Pack的关系'''
# -*- coding: cp936 -*-
# 使用文字create_text
from Tkinter import *
root = Tk()
# 改变root的大小为80x80
root
.geometry('80x80+0+0')
print root.pack_slaves()
Label(root,text = 'pack').pack()
print root.pack_slaves()
root.mainloop()
#可以看出Pack的结果没有什么变化,它不对root产生影响,也就是说Pack可以“缩小”至只包含一个Label组件,root可以自己控件自己的大小。
'''3.向Pack中添加多个组件'''
# -*- coding: cp936 -*-
# 向Pack中添加多个Label
from Tkinter import *
root = Tk()
# 改变root的大小为80x80
root
.geometry('80x80+0+0')
print root.pack_slaves()
for i in range(5):
    Label(root,text = 'pack' + str(i)).pack()
print root.pack_slaves()
root.mainloop()
# 使用用默认的设置pack将向下添加组件,第一个在最上方,然后是依次向下排列。注意最后一个Label的显示不完全,稍后解释原因
'''4.固定设置到自由变化'''
# 上例中看到label4没有显示完全
#
-*- coding: cp936 -*-
# 不设置root的大小,使用默认
from Tkinter import *
root = Tk()
#去掉下面的这句
#root
.geometry('80x80+0+0')
print root.pack_slaves()
for i in range(5):
    Label(root,text = 'pack' + str(i)).pack()
print root.pack_slaves()
root.mainloop()
#使用用默认的设置pack将向下添加组件,第一个在最上方,然后是依次向下排列。这样的话最后一个已经显示出来的,这就是为什么称Pack为弹性的容器的原因了,虽然有这个特性,但它并不是总是能够按照我们的意思进行布局,我们可以强制设置容器的大小,以覆盖Pack的默认设置。Pack的优先级低。
'''5.fill如何控制子组件的布局'''
# -*- coding: cp936 -*-
# 不设置root的大小,使用默认
from Tkinter import *
root = Tk()
# 改变root的大小为80x80
root
.geometry('80x80+0+0')
print root.pack_slaves()
# 创建三个Label分别使用不同的fill属性
Label
(root,text = 'pack1',bg = 'red').pack(fill = Y)
Label(root,text = 'pack2',bg = 'blue').pack(fill = BOTH)
Label(root,text = 'pack3',bg = 'green').pack(fill = X)
print root.pack_slaves()
root.mainloop()
#第一个只保证在Y方向填充,第二个保证在XY两个方向上填充,第三个不使用填充属性,注意Pack只会吝啬地给出可以容纳这三个组件的最小区域,它不允许使用剩余的空间了,故下方留有“空白”。
'''6.expand如何控制组件的布局'''
# -*- coding: cp936 -*-
# 这个属性指定如何使用额外的空间,即上例中留下来的“空白”
from Tkinter import *
root = Tk()
# 改变root的大小为80x80
root
.geometry('80x80+0+0')
print root.pack_slaves()
# 创建三个Label分别使用不同的fill属性
Label
(root,text = 'pack1',bg = 'red').pack(fill = Y,expand = 1)
Label(root,text = 'pack2',bg = 'blue').pack(fill = BOTH,expand = 1)
Label(root,text = 'pack3',bg = 'green').pack(fill = X,expand = 0)
print root.pack_slaves()
root.mainloop()
# 第一个只保证在Y方向填充,第二个保证在XY两个方向上填充,第三个不使用填充属性,这个例子中第一个Label和第二个Label使用了expand = 1属性,而第三个使用expand = 0属性,改变root的大小,可以看到Label1和Label2是随着root的大小变化而变化(严格地它的可用空间在变化),第三个只中使用fill进行X方向上的填充,不使用额外的空间。
'''7.改变组件的排放位置'''
# 使用side属性改变放置位置
#
-*- coding: cp936 -*-
from Tkinter import *
root = Tk()
# 改变root的大小为80x80
root
.geometry('80x80+0+0')
print root.pack_slaves()
# 创建三个Label分别使用不同的fill属性,改为水平放置
# 将第一个Label居左放置
Label
(root,text = 'pack1',bg = 'red').pack(fill = Y,expand = 1,side = LEFT)
# 将第二个Label居右放置
Label
(root,text = 'pack2',bg = 'blue').pack(fill = BOTH,expand = 1,side = RIGHT)
# 将第三个Label居左放置,靠Label放置,注意它不会放到Label1的左边
Label
(root,text = 'pack3',bg = 'green').pack(fill = X,expand = 0,side = LEFT)
print root.pack_slaves()
root.mainloop()
# 第一个只保证在Y方向填充,第二个保证在XY两个方向上填充,第三个不使用填充属性,这个例子中第一个Label和第二个Label使用了expand = 1属性,而第三个使用expand = 0属性,改变root的大小,可以看到Label1和Label2是随着root的大小变化而变化(严格地它的可用空间在变化),第三个只中使用fill进行X方向上的填充,不使用额外的空间。
'''8.设置组件之间的间隙大小'''
# ipadx设置内部间隙
# padx设置外部间隙
#
-*- coding: cp936 -*-
# 不设置root的大小,使用默认
from Tkinter import *
root = Tk()
# 改变root的大小为80x80
# root
.geometry('80x80+0+0')
print root.pack_slaves()
# 创建三个Label分别使用不同的fill属性,改为水平放置
# 将第一个LabelFrame居左放置
L1
= LabelFrame(root,text = 'pack1',bg = 'red')
# 设置ipadx属性为20
L1
.pack(side = LEFT,ipadx = 20)
Label(L1,
      text = 'inside',
      bg = 'blue'
      ).pack(expand = 1,side = LEFT)
L2 = Label(root,
           text = 'pack2',
           bg = 'blue'
           ).pack(fill = BOTH,expand = 1,side = LEFT,padx = 10)
L3 = Label(root,
           text = 'pack3',
           bg = 'green'
           ).pack(fill = X,expand = 0,side = LEFT,pady = 10)
print root.pack_slaves()
root.mainloop()
#为了演示ipadx/padx,创建了一个LabelFrame设置它的ipadx为20,即内部间隔值为20,它的子组件若使用则会留出20个单位;Label2和Label3分别设置x和y方向上的外部间隔值,所有与之排列的组件会与之保留10个单位值的距离

 


 

Place

'''Tkinter教程之Place篇'''
'''1.使用绝对坐标将组件放到指定的位置'''
# -*- coding: cp936 -*-
# 不设置root的大小,使用默认
from Tkinter import *
root = Tk()
lb = Label(root,text = 'hello Place')
# lb.place(relx = 1,rely = 0.5,anchor = CENTER)
# 使用绝对坐标将Label放置到(0,0)位置上
lb
.place(x = 0,y = 0,anchor = NW)
root.mainloop()
# x,y指定组件放置的绝对位置
'''2.使用相对坐标放置组件位置'''
# -*- coding: cp936 -*-
# 不设置root的大小,使用默认
from Tkinter import *
root = Tk()
lb = Label(root,text = 'hello Place')
# lb.place(relx = 1,rely = 0.5,anchor = CENTER)
# 使用相对坐标(0.5,0.5)将Label放置到(0.5*sx,0.5.sy)位置上
lb
.place(relx = 0.5,rely = 0.5,anchor = CENTER)
root.mainloop()
# relx,rely指定组件放置的绝对位置,范围为(0-1.0)
'''3.使用place同时指定多个组件'''
# -*- coding: cp936 -*-
# 不设置root的大小,使用默认
from Tkinter import *
root = Tk()
root.geometry('800x600')
lb = Label(root,text = 'hello Place')
# lb.place(relx = 1,rely = 0.5,anchor = CENTER)
# 使用相对坐标(0.5,0.5)将Label放置到(0.5*sx,0.5.sy)位置上
v
= IntVar()
for i in range(5):
    Radiobutton(
        root,
        text = 'Radio' + str(i),
        variable = v,
        value = i
       
).place(x = 80* i,anchor = NW)
root.mainloop()
# 使用place来指定各个Radiobutton的位置
'''4.同时使用相对和绝对坐标'''
# 同时设置relx,rely和x,y的值
#
-*- coding: cp936 -*-
# 不设置root的大小,使用默认
from Tkinter import *
root = Tk()
root.geometry('800x600')
lb1 = Label(root,text = 'hello Place',fg = 'green')
lb2 = Label(root,text = 'hello Place',fg = 'red')
# 先设置相对坐标为(0.5,0.5),再使用(-200,-200)将坐标作偏移(-200,-200)
lb1.place(relx = 0.5,rely = 0.5,anchor = CENTER,x = -200,y = -200)
# 先设置相对坐标为(0.5,0.5),再使用(-300,-300)将坐标作偏移(-300,-300)
lb2.place(relx = 0.5,rely = 0.5,anchor = CENTER,x = -300,y = -300)
root.mainloop()
# 同时使用相对和绝对坐标时,相对坐标优先操作,然后是在这个相对坐标的基础上进行偏移
'''5.使用in来指定放置的容器'''
# -*- coding: cp936 -*-
# 使用in属性来指定放置到的容器是那一个
from Tkinter import *
root = Tk()
root.geometry('800x600')
lb1 = Label(root,text = 'hello Place',fg = 'green')
bt1 = Button(root,text = 'hello Place',fg = 'red')
# 创建一个Label
lb1
.place(relx = 0.5,rely = 0.5,anchor = CENTER)

# 在root同创建一个Button,目的是与bt1相比较
bt2
= Button(root,text = 'button in root',fg = 'yellow')
bt2.place(anchor = W)
# 在Label中创建一个Button
bt1
.place(in_ = lb1,anchor = W)
root.mainloop()
# 注意bt2放置的位置是在root的(0,0)处,而button1放置的位置是在lb1的(0,0)处,原因是由于bt1使用了in来指定放置的窗口为lb1
'''6.深入in用法'''
# -*- coding: cp936 -*-
# 使用in属性来指定放置到的容器是那一个,仅能是其master
from Tkinter import *
root = Tk()
# root.geometry('800x600')
# 创建两个Frame用作容器
fm1
= Frame(root,bg = 'red',width = 40,height = 40)
fm2 = Frame(root,bg = 'blue',width = 40,height = 40)
# 再在fm1中创建一个fm3
fm3
= Frame(fm1,bg = 'yellow',width = 20,height = 20)

# 创建一个Label,它的master为fm1
lb1
= Label(fm1,text = 'hello Place',fg = 'green')
lb1.place(in_ = fm1,relx = 0.5,rely = 0.5,anchor = CENTER)
# 创建一个Button,它的master为fm1
bt1
= Button(fm1,text = 'hello Place',fg = 'red')

# 将bt1放置到fm2中,程序报错
# 去掉下面这条语句就可以使用了,可以看到lb1已经正确的放置到fm1的中心位置了
# bt1
.place(in_ = fm2,anchor = W)

# 将上面的语句改为下面,即将bt1放置到其fm1的子组件fm3中,这样也是可以的
bt1
.place(in_ = fm3,anchor = W)

fm1.pack()
fm2.pack()
fm3.pack()
root.mainloop()
# in不是可以随意指定放置的组件的,如果使用in这个参数这个组件必需满足:是其父容器或父容器的子组件
'''7.事件与Place结合使用'''
# -*- coding: cp936 -*-
# 最后使用两个place方法来动态改变两个Frame的大小。
from Tkinter import *
root = Tk()
split = 0.5
fm1
= Frame(root,bg = 'red')
fm2 = Frame(root,bg = 'blue')
# 单击fm1时增大它的占有区域0.1
def incFm1(event):
    global split
   
if split < 1:
        split += 0.1
    fm1
.place(rely = 0,relheight = split,relwidth = 1)
    fm2.place(rely = split,relheight = 1 - split,relwidth = 1)
# 单击fm2时增大它的占有区域0.1
def incFm2(event):
    global split
   
if split > 0:
        split -= 0.1
    fm1
.place(rely = 0,relheight = split,relwidth = 1)
    fm2.place(rely = split,relheight = 1 - split,relwidth = 1)

# 这两语句要使用,不然开始看不到两个frame,也就没法点击它们了
fm1
.place(rely = 0,relheight = split,relwidth = 1)
fm2.place(rely = split,relheight = 1 - split,relwidth = 1)
# 绑定单击事件
fm1
.bind('<Button-1>',incFm1)
fm2.bind('<Button-1>',incFm2)

root.mainloop()
# 为SplitWindow的原型了,再改动一下就可以实现一个SplitWindow了。
 

Grid

'''Tkinter教程之Grid篇'''
# Tkinter参考中最推荐使用的一个布局器。实现机制是将Widget逻辑上分割成表格,在指定的位置放置想要的Widget就可以了。
'''1.第一个Grid例子'''
# -*- coding: cp936 -*-
# 使用grid来布局组件
from Tkinter import *
root = Tk()
# 创建两个Label
lb1
= Label(root,text = 'Hello')
lb2 = Label(root,text = 'Grid')

lb1.grid()
lb2.grid()

root.mainloop()
# grid有两个最为重要的参数,用来指定将组件放置到什么位置,一个是row,另一个是column。如果不指定row,会将组件放置到第一个可用的行上,如果不指定column,则使用第一列。
'''2.使用row和column来指定位置'''
# -*- coding: cp936 -*-
# 使用grid来布局组件
from Tkinter import *
root = Tk()
# 创建两个Label
lb1
= Label(root,text = 'Hello')
lb2 = Label(root,text = 'Grid')

lb1.grid()
# 指定lb2为第一行(使用索引0开始),第二列(使用索引0开始)
lb2
.grid(row = 0,column = 1)

root.mainloop()
# grid有两个最为重要的参数,用来指定将组件放置到什么位置,一个是row,另一个是column。如果不指定row,会将组件放置到第一个可用的行上,如果不指定column,则使用第一列。注意这里使用grid时不需要创建,直接使用行列就可以。
'''3.为其它组件预定位置'''
# 可以使用row/column来指定组件的放置位置,并预先留出空间,以务其它需要。
#
-*- coding: cp936 -*-
# 使用grid来布局组件
from Tkinter import *
root = Tk()
# 创建两个Label
Label
(root,text = 'Hello').pack()
# 在第一行,第10列放置lb2
Label
(root,text = 'Grid').grid(row = 0,column = 10)
# Lable(root,text = '3').grid(row = 0,column = 5)
root.mainloop()
# 这个例子中将lb2放置到第1行,第11列位置上,但运行结果与上一例从效果上看不出太大的区别。原因是:如果这个位置没有组件的话,它是看不可见的。
'''4.将组件放置到预定位置上去'''
# -*- coding: cp936 -*-
# 使用grid来布局组件
from Tkinter import *
root = Tk()
# 创建两个Label
Label
(root,text = '1').grid()
# 在第1行,第11列放置lb2
Label
(root,text = '2').grid(row = 0,column = 10)
Label(root,text = '3').grid(row = 0,column = 5)
root.mainloop()
# 可以看到Label('3')是位置Label('1')和Label('2')之间了,即Label('2')是在11列,Label('3')位于第3列
'''5.将两个或多个组件同一个位置'''
# -*- coding: cp936 -*-
# 多个组件同时grid到同一个表格位置
from Tkinter import *
root = Tk()
# 创建两个Label
lb1
= Label(root,text = '1')
lb2 = Label(root,text = '2')

# 将lb1和lb2均grid到(0,0)位置
lb1
.grid(row = 0,column = 0)
lb2.grid(row = 0,column = 0)

def forgetLabel():
    # grid_slaves返回grid中(0,0)位置的所有组件
    # grid_forget将这个组件从grid中移除(并未删除,可以使用grid再将它显示出来
)
    print root.grid_slaves(0,0)[0].grid_forget()

# 我测试时grid_salves返回的第一个值为lb2,最后grid的那一个
Button
(root,text = 'forget last',command = forgetLabel).grid(row = 1)

root.mainloop()
# 这段代码是用来证明,多个组件同时放置到同一个位置上会产生覆盖的问题。对于grid_slaves返回的组件list如何排序,我没有去查想着资料,在这个例子中使用索引0,返回的正好是lb2,然后再使用grid_forget将这个删除从grid中移除,可以看到lb1显示出来了。
'''6.改变列(行)的属性值'''
# -*- coding: cp936 -*-
# 设置column的属性(columnconfigure)
from Tkinter import *
root = Tk()
# 创建两个Label
lb1
= Label(root,text = '1',bg = 'red')
lb2 = Label(root,text = '2',bg = 'blue')

# 将lb1和lb2分别放置到第1行的1,2列位置上
lb1
.grid(row = 0,column = 0)
lb2.grid(row = 0,column = 1)

# 指定列的最小宽度为100
root
.columnconfigure(0,minsize = 100)
root.mainloop()
# 1与2的距离变的远一些了。
# 但如果这个位置没有组件存在的话这个值是不起作用的
.
# 设置列或行(rowconfigure)的属性时使用父容器的方法,不是自己调用。
'''7.组件使用多列(多行)'''
# -*- coding: cp936 -*-
# 使用多行(多列)
from Tkinter import *
root = Tk()
# 创建如下布局(一个字符占用一个grid位置)
# A E
# B C
# D
# A占用
(0,0)(0,1),B占用(1,0),C占用(1,1),D占用(2,0),E占用(0,2)
# 创建5个Label,分别以背景色区别
lbA
= Label(root,text = 'A',bg = 'red')
lbB = Label(root,text = 'B',bg = 'blue')
lbC = Label(root,text = 'C',bg = 'red')
lbD = Label(root,text = 'D',bg = 'blue')
lbE = Label(root,text = 'E',bg = 'blue')
# 以下为布局参数设置
lbA
.grid(row = 0,column = 0,columnspan = 2)
lbB.grid(row = 1,column = 0)
lbC.grid(row = 1,column = 1)
lbD.grid(row = 2)
lbE.grid(row = 0,column = 2)

root.mainloop()
# A与B、D的区别,它左边已改变,由于使用了两个表格;
# C与E的区别:C的右边与E的左边对齐,也就是说E被放置到第2列的下一个位置了,原因由于A已使用了第2列。

'''8.设置表格中组件的对齐属性'''
# -*- coding: cp936 -*-
# 使用sticky设置对齐方式
from Tkinter import *
root = Tk()
# 创建两个Label
Label
(root,text = 'hello sticky').grid()
Label(root,text = 'Tkinter').grid()
# 创建两个Label,并指定sticky属性
Label
(root,text = 'hello sticky').grid(sticky = W)
Label(root,text = 'Tkinter').grid(sticky = W)

root.mainloop()
# 默认属性下,组件的对齐方式为居中,设置sticky属性可以控制对齐方式,可用的值(N,S,E,W)及其组合值

Font

'''Tkinter教程之Font篇'''
# Tkinter中其它常用的一些功能
'''1.字体使用'''
# -*- coding: cp936 -*-
# 改变组件的显示字体
from Tkinter import *
root = Tk()
# 创建一个Label
for ft in ('Arial',('Courier New',),('Comic Sans MS',),'Fixdsys',('MS Sans Serif',),('MS Serif',),'Symbol','System',('Times New Roman',),'Verdana'):
    Label(root,text = 'hello sticky',font = ft ).grid()

root.mainloop()
# 在Windows上测试字体显示,注意字体中包含有空格的字体名称必须指定为tuple类型。
'''2.使用系统已有的字体'''
# -*- coding: cp936 -*-
# Font来创建字体
from Tkinter import *
# 引入字体模块
import tkFont
root
= Tk()
# 创建一个Label
# 指定字体名称、大小、样式
ft
= tkFont.Font(family = 'Fixdsys',size = 20,weight = tkFont.BOLD)
Label(root,text = 'hello sticky',font = ft ).grid()

root.mainloop()
# 使用tkFont.Font来创建字体。
'''3.字体创建属性优先级'''
# -*- coding: cp936 -*-
# 使用系统已有的字体显示
from Tkinter import *
import tkFont
root
= Tk()
# 创建一个Label
# 指定字体名称、大小、样式
# 名称是系统可使用的字体
ft1
= tkFont.Font(family = 'Fixdsys',size = 20,weight = tkFont.BOLD)
Label(root,text = 'hello sticky',font = ft1 ).grid()

ft2 = tkFont.Font(font = ('Fixdsys','10',tkFont.NORMAL),size = 40)
Label(root,text = 'hello sticky',font = ft2).grid()

root.mainloop()
# 创建字体有font等其它属性,
# 如果font指定了,有几个参数将不再起作用,如:family
,size,weight,slant,underline,overstrike
#
例子中演示的结果是ft2中字体大小为10,而不是40
'''4.得到字体的属性值'''
# -*- coding: cp936 -*-
# 测试measure和metrics属性
from Tkinter import *
import tkFont
root
= Tk()
# 创建一个Label
ft1
= tkFont.Font(family = 'Fixdsys',size = 20,weight = tkFont.BOLD)
Label(root,text = 'hello font',font = ft1 ).grid()

ft2 = tkFont.Font(font = ('Fixdsys','10',tkFont.NORMAL),size = 40)
Label(root,text = 'hello font',font = ft2).grid()

# 得到字体的宽度
print ft1.measure('hello font')
print ft2.measure('hello font')

# 打印两个字体的属性
for metric in ('ascent','descent','linespace','fixed'):
    print ft1.metrics(metric)
    print ft2.metrics(metric)
root.mainloop()
# 使用这两个方法得到已创建字体的相关属性值
'''5.使用系统指定的字体'''
# -*- coding: cp936 -*-
# 使用系统字体:以下测试是Windows上的系统指定字体
from Tkinter import *
import tkFont
root
= Tk()
for ft1 in ('ansi','ansifixed','device','oemfixed','system','systemfixed'):
    Label(root,text = 'hello font',font = ft1 ).grid()

root.mainloop()
# X Window上的系统指定字体:fixed,6x10
'''6.使用X Font Descriptor'''
# -*- coding: cp936 -*-
# 使用X Font Descriptor
from Tkinter import *
import tkFont
root
= Tk()
for ft in ('Times','Helvetica','Courier','Symbol',):
    Label(root,text = 'hello font',font = ('-*-%s-*-*-*--*-240-*')%(ft)).grid()

root.mainloop()
# X Font Descriptor格式:-*-family-weight-slant-*--*-size-*-*-*-*-charset
#
这个例子是在Windows下测试,没有在Linux测试。

tkCommonDialog

'''Tkinter教程之tkCommonDialog篇'''
'''1.使用用模态对话框SimpleDialg'''
from Tkinter import *
# 引入SimpleDialog模态对话框
from SimpleDialog import *

root = Tk()
# 创建一个SimpleDialog
# buttons
:显示的按钮
# default
:默认选中的按钮
dlg
= SimpleDialog(root,
                   text = 'hello SimpleDialog',
                   buttons = ['Yes','No','cancel'],
                   default = 0,
                   )
# 执行对话框
print dlg.go()
root.mainloop()
# 返回值为点击的按钮在buttons中的索引值
'''2.使用tkSimpleDialog模块'''
from Tkinter import *
# 引入SimpleDialog模态对话框
from tkSimpleDialog import *

root = Tk()
# 输入一个整数,
# initialvalue指定一个初始值
# prompt提示信息
# title提示框标题

print askinteger(title = 'prompt',prompt = 'input a integer:',initialvalue = 100)
# 输入一浮点数
# minvalue指定最小值
# maxvalue指定最大值,如果不在二者指定范围内则要求重新输入

print askfloat(title = 'float',prompt = 'input a float',minvalue = 0,maxvalue = 11)
# 输入一字符串
print askstring(title = 'string',prompt = 'input a string')
root.mainloop()
# 返回值为各自输入的值。
'''2.打开文件对话框'''
from Tkinter import *
from FileDialog import *

root = Tk()
# 指定master就可以了。
# title属性用来指定标题
fd
= LoadFileDialog(root)
# go方法的返回值即为选中的文本路径,如果选择取返回值则为None
print fd.go()
root.mainloop()
# 返回选中的文件名称
'''3.保存文件对话框'''
# 与LoadFileDialog正好操作相反,这个类是用来保存文件。
# 各个 参数的意义都 一样,只是ok的返回值为保存的文件名称;如果取消则为None

from Tkinter import *
from FileDialog import *

root = Tk()
# 指定master就可以了。
# title属性用来指定标题
fd
= SaveFileDialog(root)
# go方法的返回值即为选中的文本路径,如果选择取返回值则为None
print fd.go()
root.mainloop()
# 返回选中的文件名称

'''4.使用颜色对话框'''
from Tkinter import *
# 引入tkColorChoose模块
from tkColorChooser import *
root = Tk()

# 调用askcolor返回选中颜色的(R,G,B)颜色值及#RRGGBB表示
print askcolor()
root.mainloop()
# 返回选中的文件名称
'''5. 使用消息对话框'''
# -*- coding: cp936 -*-
# 使用提示对话框模块tkMessageBox
from Tkinter import *
# 引入tkMessageBox模块
from tkMessageBox import *
root = Tk()
stds = [
    showinfo, # 显示信息消息框
    showwarning
, # 显示警告消息框
    showerror
, # 显示错误消息框
    askquestion
, # 显示询问消息框
    askokcancel
, # 显示确认/取消消息框
    askyesno
, # 显示是/否消息框
    askretrycancel # 显示重试
/取消消息框
   
]
for std in stds:
    print str(std),std(title = str(std),message = str(std))
# 程序打印输出结果如下(与点击的按钮得到不同其值)
#
<function showinfo at 0x00D589F0> ok
#
<function showwarning at 0x00D58A30> ok
#
<function showerror at 0x00D58A70> ok
#
<function askquestion at 0x00D58AB0> yes
#
<function askokcancel at 0x00D58AF0> False
#
<function askyesno at 0x00D58B30> True
#
<function askretrycancel at 0x00D58B70> True
root
.mainloop()
# 如果要确认点击的是那一个按钮,则可以判断这个消息框的返回值,注意各个值有所不同
# 返回值有ok
/yes/True
'''使用缺省焦点'''
# -*- coding: cp936 -*-
# 使用提示对话框模块tkMessageBox缺省焦点
from Tkinter import *
from tkMessageBox import *
root = Tk()
print askokcancel(title = 'quit application?',
                  message = 'would you like quit this application',
                  default = CANCEL # 指定默认焦点位置
                 
)

root.mainloop()
# 使用default来指定默认焦点位置,ABORT/RETRY/IGNORE/OK/CANCEL/YES/NO
#
如果指定的按钮不存在,在抛出异常
 

Event(1)

  1. '''Tkinter教程之Event篇(1)'''
    # 事件的使用方法
    '''1.测试鼠标点击(Click)事件'''
    # -*- coding: cp936 -*-
    # 测试鼠标点击事件
    from Tkinter import *
    root = Tk()
    def printCoords(event):
        print event.x,event.y
    #
    创建第一个Button,并将它与左键事件绑定
    bt1
    = Button(root,text = 'leftmost button')
    bt1.bind('<Button-1>',printCoords)

    # 创建二个Button,并将它与中键事件绑定
    bt2
    = Button(root,text = 'middle button')
    bt2.bind('<Button-2>',printCoords)

    # 创建第三个Button,并将它与右击事件绑定
    bt3
    = Button(root,text = 'rightmost button')
    bt3.bind('<Button-3>',printCoords)

    # 创建第四个Button,并将它与双击事件绑定
    bt4
    = Button(root,text = 'double click')
    bt4.bind('<Double-Button-1>',printCoords)

    # 创建第五个Button,并将它与三击事件绑定
    bt5
    = Button(root, text = 'triple click')
    bt5.bind('<Triple-Button-1>',printCoords)

    bt1.grid()
    bt2.grid()
    bt3.grid()
    bt4.grid()
    bt5.grid()

    root.mainloop()
    # 分别测试鼠标的事件,回调函数的参数event中(x,y)表示当前点击的坐标值
    '''2.测试鼠标的移动(Motion)事件'''
    # -*- coding: cp936 -*-
    # 测试鼠标移动事件
    from Tkinter import *
    root = Tk()
    def printCoords(event):
        print event.x,event.y
    #
    创建第一个Button,并将它与左键移动事件绑定
    bt1
    = Button(root,text = 'leftmost button')
    bt1.bind('<B1-Motion>',printCoords)

    # 创建二个Button,并将它与中键移动事件绑定
    bt2
    = Button(root,text = 'middle button')
    bt2.bind('<B2-Motion>',printCoords)

    # 创建第三个Button,并将它与右击移动事件绑定
    bt3
    = Button(root,text = 'rightmost button')
    bt3.bind('<B3-Motion>',printCoords)


    bt1.grid()
    bt2.grid()
    bt3.grid()

    root.mainloop()
    # 分别测试鼠标的移动事件,只有当鼠标被按下后移动才回产生事件
    '''3.测试鼠标的释放(Relase)事件'''
    # -*- coding: cp936 -*-
    # 测试鼠标释放事件
    from Tkinter import *
    root = Tk()
    def printCoords(event):
        print event.x,event.y
    #
    创建第一个Button,并将它与左键释放事件绑定
    bt1
    = Button(root,text = 'leftmost button')
    bt1.bind('<ButtonRelease-1>',printCoords)

    # 创建二个Button,并将它与中键释放事件绑定
    bt2
    = Button(root,text = 'middle button')
    bt2.bind('<ButtonRelease-2>',printCoords)

    # 创建第三个Button,并将它与右击释放事件绑定
    bt3
    = Button(root,text = 'rightmost button')
    bt3.bind('<ButtonRelease-3>',printCoords)


    bt1.grid()
    bt2.grid()
    bt3.grid()

    root.mainloop()
    # 分别测试鼠标的Relase事件,只有当鼠标被Relase后移动才回产生Relase事件
    '''4.进入(Enter)事件'''
    # -*- coding: cp936 -*-
    # 测试鼠标释放事件
    from Tkinter import *
    root = Tk()
    def printCoords(event):
        print event.x,event.y
    #
    创建第一个Button,并将它与Enter事件绑定
    bt1
    = Button(root,text = 'leftmost button')
    bt1.bind('<Enter>',printCoords)

    bt1.grid()

    root.mainloop()
    # 分别测试Enter事件,只是在第一次进入进回产生事件,在组件中移动不会产生Enter事件。
     

Event(2)

'''Tkinter教程之Event篇(2)'''
'''5.测试离开(Leave)事件'''
# -*- coding: cp936 -*-
# 测试鼠标释放事件
from Tkinter import *
root = Tk()
def printCoords(event):
    print event.x,event.y
#
创建第一个Button,并将它与Enter事件绑定
bt1
= Button(root,text = 'leftmost button')
bt1.bind('<Leave>',printCoords)

bt1.grid()

root.mainloop()
# 分别测试Leave事件,只是在离开组件是会产生此事件。
'''6.响应特殊键(Special Key)'''
# -*- coding: cp936 -*-
# 测试键盘特殊键事件
from Tkinter import *
root = Tk()
def printCoords(event):
    print 'event.char = ',event.char
   
print 'event.keycode = ',event.keycode
#
创建第一个Button,并将它与BackSpace键绑定
bt1
= Button(root,text = 'Press BackSpace')
bt1.bind('<BackSpace>',printCoords)

# 创建二个Button,并将它与回车键绑定
bt2
= Button(root,text = 'Press Enter')
bt2.bind('<Return>',printCoords)

# 创建第三个Button,并将它与F5键绑定
bt3
= Button(root,text = 'F5')
bt3.bind('<F5>',printCoords)

# 创建第4个Button,并将它与左Shift键绑定,与参考上说法一致
bt4
= Button(root,text = 'Left Shift')
bt4.bind('<Shift_L>',printCoords)

# 创建第5个Button,并将它与右Shift键绑定,与参考上说法一致
bt5
= Button(root,text = 'Right Shift')
bt5.bind('<Shift_R>',printCoords)


# 将焦点设置到第1个Button上
bt1
.focus_set()
bt1.grid()
bt2.grid()
bt3.grid()
bt4.grid()
bt5.grid()

root.mainloop()
# 各个组件间焦点的切换可以使用TAB键。
# 特殊键    Cancel
/Break/BackSpace/Tab/Return/Sift_L/Shift_R/Control_L/Control_R/Alt_L/Alt_R/Pause
#        Caps_Loack
/Escape/Prior(Page Up)/Next(Page Down)/End/Home/Left/Up/Right/Down/Print/Insert/Delete/
#        F1-12/Num_Lock/Scroll_Lock
#
这些键的char是不可打印的,可以使用event.keycode查看。
'''7.响应所有的按键(Key)事件'''
# -*- coding: cp936 -*-
# 使用Key处理所有的键盘事件
from Tkinter import *
root = Tk()
def printCoords(event):
    print 'event.char = ',event.char
   
print 'event.keycode = ',event.keycode
#
创建第一个Button,并将它与Key键绑定
bt1
= Button(root,text = 'Press BackSpace')
bt1.bind('<Key>',printCoords)

# 将焦点设置到第1个Button上
bt1
.focus_set()
bt1.grid()

root.mainloop()
# 处理所有的按键事件,如果是上例的特殊键,event.char返回为空;其它情况下为这个键的值。
# 如果输入大写字母(即上档键值),按下Shift键时就会有Key的事件触发。即回将用两次:一次为Shift本身,另一次为Shift
+ Kye的实际键值。
'''8.只处理指定的按键消息'''
# -*- coding: cp936 -*-
# 只处理指定的按键消息
from Tkinter import *
root = Tk()
def printCoords(event):
    print 'event.char = ',event.char
   
print 'event.keycode = ',event.keycode
#
创建第一个Button,并将它与键'a'绑定
bt1
= Button(root,text = 'Press BackSpace')
bt1.bind('a',printCoords)

# 创建二个Button,并将它与按下spacebar是触发事件
bt2
= Button(root,text = 'Press spacebar')
bt2.bind('<space>',printCoords)

# 创建第三个Button,并将它与'<'键绑定
bt3
= Button(root,text = 'less than key')
bt3.bind('<less>',printCoords)

# 将焦点设置到第1个Button上
bt1
.focus_set()

bt1.grid()
bt2.grid()
bt3.grid()

root.mainloop()
# 一般的按键直接使用就可以了,这样书写'key',不是'<key>';
# 但有两个需要特别注意:空格与小于的处理,使用方式为'<space>和<less>
 

Event(3)

'''Tkinter教程之Event篇(3)'''
'''11.两个事件同时绑定到一个控件'''
# 将两个事件绑定为同一个组件
#
-*- coding: cp936 -*-
# 为root绑定两个事件
from Tkinter import *
root = Tk()
# Key事件处理函数
def printEvent(event):
    print '<Key>',event.keycode
# Return
事件处理函数
def printReturn(event):
    print '<Return>',event.keycode
root
.bind('<Key>',printEvent)
root.bind('<Return>',printReturn)

root.mainloop()
# 当按键除了Return之外,都是由printEvent来处理
# 当按键为Return时,由printReturn来处理
,即由最“近”的那个事件处理
'''12.为一个instance绑定一个事件。'''
# instance的bind方法
#
-*- coding: cp936 -*-
from Tkinter import *
root = Tk()
# Key事件处理函数
def printEvent(event):
    print '<Key>',event.keycode
# Return
事件处理函数
def printReturn(event):
    print '<Return>',event.keycode
#
使用bt1来添加一个事件处理函数。
bt1
= Button(root,text = 'instance event')
bt1.bind('<Key>',printEvent)
bt1.focus_set()
bt1.grid()

root.mainloop()
# 当按键时,程序调用一次printEvent
'''13.事件各个级别音传递'''
# -*- coding: cp936 -*-
# 事件级别间”传递"
from Tkinter import *
root = Tk()
# Key事件处理函数
def printEvent(event):
    print '<instance>',event.keycode
# Return事件处理函数
def printToplevel(event):
    print '<toplevel>',event.keycode
def printClass(event):
    print '<bind_class>',event.keycode
def printAppAll(event):
    print '<bind_all>',event.keycode

# 在instance级别与printEvent绑定
bt1 = Button(root,text = 'instance event')
bt1.bind('<Return>',printEvent)

# 在bt1的Toplevel级别与printToplevel绑定
bt1.winfo_toplevel().bind('<Return>',printToplevel)

# 在class级别绑定事件printClass
root.bind_class('Button','<Return>',printClass)

# 在application all级别绑定printAppAll
bt1.bind_all('<Return>',printAppAll)

# 将焦点定位到bt1上,回车一下,结果有4个打印输出。
bt1.focus_set()
bt1.grid()

root.mainloop()
# 输出结果:
# <instance> 13
# <bind_class> 13
# <toplevel> 13
# <bind_all> 13
# Return向高级别进行了“传递",调用顺序为instance/class/toplevel/all
'''14.使用bind_class的后果'''
# -*- coding: cp936 -*-
# 使用bind_class将影响所有这个类的instance
from Tkinter import *
root = Tk()

def printClass(event):
    print '<bind_class>',event.keycode

#
改变button类的事件绑定
root
.bind_class('Button','<Return>',printClass)
# 创建两个Button
bt1
= Button(root,text = 'a button')
bt2 = Button(root,text = 'another button')

bt1.focus_set()
bt1.grid()
bt2.grid()

root.mainloop()
# 回车,bt1打印结果
# TAB切换到bt2
,回车同样打印出结果,即所有的Button对Return事件进行响应。
'''15.使用protocol绑定'''
# -*- coding: cp936 -*-
# 使用protocol与WM交互
from Tkinter import *
root = Tk()

def printProtocol():
    print 'WM_DELETE_WINDOW'
    root.destroy()

# 使用protocol将WM_DELETE_WINDOW与printProtocol绑定
root
.protocol('WM_DELETE_WINDOW',printProtocol)
root.mainloop()
# 程序在退出时打印'WM_DELETE_WINDOW'
 

 



 

猜你喜欢

转载自blog.csdn.net/weixin_41738417/article/details/81944203
今日推荐