转-Tkinter完整教程 15-23

15 Frame

Frame就是屏幕上的一块矩形区域,多是用来作为容器(container)来布局窗体。

15.1 创建Frame并添加Widget

'''1.创建Frame'''
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'''
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时再介绍

15.2 LabelFrame

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

16 PanedWindow

介绍

Tkinter PanedWindow: 一个PanedWindow是一个容器部件可能包含任何数量的窗格,水平或垂直排列

一个PanedWindow是一个容器部件可能包含任何数量的窗格,水平或垂直排列.

每个窗格中包含一个部件,每一双窗格由一个可移动的(通过鼠标移动)窗扇分开。移动窗扇导致要么被调整窗框侧面的部件.

Option Description
bg The color of the slider and arrowheads when the mouse is not over them.
bd The width of the 3-d borders around the entire perimeter of the trough, and also the width of the 3-d effects on the arrowheads and slider. Default is no border around the trough, and a 2-pixel border around the arrowheads and slider.
borderwidth Default is 2.
cursor The cursor that appears when the mouse is over the window.
handlepad Default is 8.
handlesize Default is 8.
height No default value.
orient Default is HORIZONTAL.
relief Default is FLAT.
sashcursor No default value.
sashrelief Default is RAISED.
sashwidth Default is 2.
showhandle No default value
width No default value.
Methods & Description
add(child, options) Adds a child window to the paned window.
get(startindex [,endindex]) This method returns a specific character or a range of text.
config(options) Modifies one or more widget options. If no options are given, the method returns a dictionary containing all current option values.

例子

from Tkinter import *  
  
m = PanedWindow(orient=VERTICAL)  
m.pack(fill=BOTH, expand=1)  
  
top = Label(m, text="top pane")  
m.add(top)  
  
bottom = Label(m, text="bottom pane")  
m.add(bottom)  
  
mainloop()  
from Tkinter import *

m1 = PanedWindow()
m1.pack(fill=BOTH, expand=1)

left = Label(m1, text="left pane")
m1.add(left)

m2 = PanedWindow(m1, orient=VERTICAL)
m1.add(m2)

top = Label(m2, text="top pane")
m2.add(top)

bottom = Label(m2, text="bottom pane")
m2.add(bottom)

mainloop()

17 Toplevel

TopLevel与Frame类似,但它包含窗体属性(如Title)

17.1 创建简单的Toplevel

'''Tkinter教程之Toplevel篇'''
'''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也结束,它不能单独存在。

17.2 设置Toplevel的属性

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

17.3 使用Toplevel自己制作提示框

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

18 Canvas 绘制矩形

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

18.1 绘制简单矩形

'''Tkinter教程之Canvas篇(1)'''
'''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

18.2 指定item的填充色

'''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()
# 指定矩形的填充色为红色

18.3 指定item的边框颜色

'''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()
# 指定矩形的边框颜色为红色

18.4 指定边框的宽度

'''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是不同的。

18.5 画虚线

'''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()
# 指定矩形的边框颜色为红色,画虚线

18.6 修改item的坐标(移动)

'''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的坐标

18 Canvas之Tags

18.7 创建item的tags

'''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的坐标

18.8 多个item使用同一个tag

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

18.9 通过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边框颜色

18.10 向其它item添加tag

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

18.11 返回其它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

18 Canvas(3)

18.12 移动item

'''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在相对偏移量,可以为负值

18.13 删除item

'''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.14 缩放item

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

18.15 绑定item与event

'''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()
# 只有点击到矩形的边框时才会触发事件

18.16 添加绑定事件

'''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添加一个处理函数,它不会替换原来的事件函数,例子结果:既响应左键又响应右键

18.17 绑定新的item与现有的tags

'''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同样也与事件绑定,这个与参考上的说法也不一致

18 Canvas(4)

18.18 绘制弧形

'''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指定角度偏移

18.19 绘制位图

'''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)指定位图存放位置的左上位置。

18.20 绘制彩色图像

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

18.21 绘制直线

'''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,测试其效果。

18.22 绘制椭圆

'''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()
# 指定椭圆的长和宽,圆是长和宽相等的特殊情况。

18.23 绘制多边形

'''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用来修改绘制的图形,不明白这两个参数还有其它什么作用。

18.24 绘制文字

'''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控制对齐方式

18.25 Canvas中创建组件

'''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战胜的那块区域

19 布局管理pack

19.1 一个空的widget

'''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打印当前组件包拥有的子组件,通过这个函数可以查看各个组件是否有包含关系。

19.2 root与Pack的关系

'''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可以自己控件自己的大小。

19.3 向Pack中添加多个组件

'''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的显示不完全,稍后解释原因

19.4 固定设置到自由变化

'''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的优先级低。

19.5 fill,expand,side


'''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方向上的填充,不使用额外的空间。

19.6 设置组件之间的间隙大小

'''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个单位值的距离

20 布局管理grid

20.1 row和column来制定位置

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

20.2 将两个或多个组件同一个位置

'''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显示出来了。

20.3 改变列(行)的属性值

'''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)的属性时使用父容器的方法,不是自己调用。

20.4 组件使用多列(多行)

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

20.5 设置表格中组件的对齐属性

'''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)及其组合值

21 布局管理place

21.1 使用绝对坐标将组件放到指定的位置

'''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指定组件放置的绝对位置

21.2 使用相对坐标放置组件位

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

21.3 使用place同时指定多个组件

'''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的位置

21.4 同时使用相对和绝对坐标

'''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()
# 同时使用相对和绝对坐标时,相对坐标优先操作,然后是在这个相对坐标的基础上进行偏移

21.5 使用in_来指定放置的容器

'''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这个参数这个组件必需满足:是其父容器或父容器的子组件

21.6 事件与Place结合使用

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

22 标准对话框 MessageBox, FileDialog, colorChooser

'''Tkinter教程之tkCommonDialog篇'''
'''1.使用用模态对话框SimpleDialg'''
# SimpleDialog:创建一个模态对话框
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模块'''
# askinteger:输入一个整数值
# askfloat:输入一个浮点数
# askstring:输入一个字符串
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.打开文件对话框'''
# LoadFileDialog:打开对话框
from Tkinter import *
from FileDialog import *

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

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

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

# 调用askcolor返回选中颜色的(R,G,B)颜色值及#RRGGBB表示
print askcolor()
root.mainloop()
# 返回选中的文件名称
'''5. 使用消息对话框'''
# -*- coding: cp936 -*-
# showinfo:信息对话框
# showwarning:警告对话框
# showerror:错误对话框
# showquestion:询问对话框  
# showokcancel:显示确定/取消对话框  
# showyesno:是/否对话框
# showretrycancel:重试/取消对话框
# 使用提示对话框模块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
'''6.使用缺省焦点'''
# -*- coding: cp936 -*-
# default:指定默认焦点位置
# 使用提示对话框模块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
# 如果指定的按钮不存在,在抛出异常

23 Event(1)

23.1 测试鼠标点击(Click)事件

'''Tkinter教程之Event篇(1)'''
# 事件的使用方法
'''1.测试鼠标点击(Click)事件'''
# -*- coding: cp936 -*-
# <Button-1>:鼠标左击事件
# <Button-2>:鼠标中击事件
# <Button-3>:鼠标右击事件
# <Double-Button-1>:双击事件
# <Triple-Button-1>:三击事件
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)表示当前点击的坐标值

23.2 测试鼠标的移动(Motion)事件

'''2.测试鼠标的移动(Motion)事件'''
# -*- coding: cp936 -*-
# <Bx-Motion>:鼠标移动事件,x=[1,2,3]分别表示左、中、右鼠标操作。
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()
# 分别测试鼠标的移动事件,只有当鼠标被按下后移动才回产生事件

23.3 测试鼠标的释放(Relase)事件

'''3.测试鼠标的释放(Relase)事件'''
# -*- coding: cp936 -*-
# <ButtonRelease-x>鼠标释放事件,x=[1,2,3],分别表示鼠标的左、中、右键操作
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事件

23.4 进入(Enter)事件

'''4.进入(Enter)事件'''
# -*- coding: cp936 -*-
# <Enter>:鼠标释放事件
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事件。

23 Event(2)

23.5 测试离开(Leave)事件

'''Tkinter教程之Event篇(2)'''
'''5.测试离开(Leave)事件'''
# -*- coding: cp936 -*-
# leave:鼠标离开时产生此事件
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事件,只是在离开组件是会产生此事件。

23.6 响应特殊键(Special Key)

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

23.7 响应所有的按键(Key)事件

'''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的实际键值。

23.8 只处理指定的按键消息

'''8.只处理指定的按键消息'''
# -*- coding: cp936 -*-
# a:只处理指定的按键消息
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>

23.9 使用组合键响应事件

'''9.使用组合键响应事件'''
# -*- coding: cp936 -*-
# 组合键(Control/Alt/Shift)
from Tkinter import *
root = Tk()
def printCoords(event):
    print 'event.char = ',event.char
    print 'event.keycode = ',event.keycode
# 创建第一个Button,并将它与键Shift - Up绑定
bt1 = Button(root,text = 'Press Shift - Up')
bt1.bind('<Shift-Up>',printCoords)

# 创建二个Button,并将它与按下Control-Alt-a时触发事件
bt2 = Button(root,text = 'Control-Alt-a')
bt2.bind('<Control-Alt-a>',printCoords)

# 下面的按键处理将无法接受
# 创建第三个Button,并将它与'Control-Alt'键绑定
# bt3 = Button(root,text = 'Control-Alt')
# bt3.bind('<Control-Alt>',printCoords)


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

root.mainloop()
# 使用Control/Alt/Shift与其它按键组合,但不能单独的使用Control/Alt组合。

23.10 改变组件大小事件

'''10.改变组件大小事件'''
# -*- coding: cp936 -*-
# configure:改变组件大小事件
from Tkinter import *
root = Tk()
def printSize(event):
    print (event.width,event.height)
root.bind('<Configure>',printSize)

root.mainloop()
# 当组件的大小改变时触发。evnet.width/height分别返回改变后的宽度和高度。

23 Event(3)

23.11 两个事件同时绑定到一个控件

# 11.两个事件同时绑定到一个控件
# -*- coding: cp936 -*-
# bind:将事件与处理函数
# 将两个事件绑定为同一个组件
# 为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来处理,即由最“近”的那个事件处理。

23.12 为一个instance绑定一个事件

'''12.为一个instance绑定一个事件。'''
# bind:绑定instance的事件处理函数
# -*- 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

23.13 事件各个级别间传递

'''13.事件各个级别音传递'''
# -*- coding: cp936 -*-
# bind:绑定instance与toplevel
# bind_class:绑定类处理函数
# bind_all:绑定应用所有事件
# 事件级别间”传递"
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

23.14 使用bind_class的后果

'''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事件进行响应。

23.15 使用protocal绑定

'''15.使用protocal绑定'''
# -*- 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'
Table of Contents