tkinter 19 canvas
Reference
- http://effbot.org/tkinterbook/canvas.htm
- http://bbs.fishc.com/thread-60116-1-1.html
简介
Canvas(画布)组件为 Tkinter 的图形绘制提供了基础。它提供可以用来进行绘图的Container,支持基本的几何元素,使用Canvas进行绘图时,所有的操作都是通过Canvas,不是通过它的元素, 元素的表示可以使用handle或tag。
绘制图形
Canvas 是一个高度灵活的组件,你可以用它绘制图形和图表,创建图形编辑器,并实现各种自定义的小部件。简单的使用总结:
- 在 Canvas 组件上绘制对象,可以用 create_xxx() 的方法(xxx 表示对象类型,例如线段 line,矩形 rectangle,文本 text 等)
- create_line,画线
- create_text() 方法,可以在 Canvas 上显示文本,
- create_oval() 绘制椭圆形/圆形,参数是指定一个限定矩形(在这个矩形内绘制一个椭圆)
- Tkinter 并没有提供画“点”的方法。不过,我们可以通过绘制一个超小的椭圆形来表示一个“点”
- create_polygon() 绘制多边形
- create_rectangle() 绘制矩形
- create_window() 创建组件
- create_arc(), 绘制弧形、弦或扇形)
- create_bitmap(position, **options),绘制内建的位图文件或 XBM 格式的文件
- create_image(position, **options),绘制BitmapImage 或 PhotoImage 的实例对象
- NOTE:弦、扇形、椭圆形、圆形、多边形和矩形这些“封闭式”图形都是由轮廓线和填充颜色组成的,但都可以设置为透明(传入空字符串表示透明)
- 添加到 Canvas 上的对象会一直保留直着。如果你希望修改它们,你可以使用 coords(),itemconfig() 和 move() 方法来移动画布上的对象,或者使用 delete() 方法来删除
- 画布对象/图形的显示顺序
- Canvas 组件中创建的画布对象都会被列入显示列表中,越接近背景的画布对象位于显示列表的越下方
- 当两个画布对象重叠的时候,默认情况下新创建的会覆盖旧的画布对象的重叠部分,即位于显示列表上方的画布对象将覆盖下方那个。
- 显示列表中的画布对象可以被重新排序
坐标系
由于画布可能比窗口大(带有滚动条的 Canvas 组件),因此 Canvas 组件可以选择使用两种坐标系:
- 窗口坐标系:以窗口的左上角作为坐标原点
- 画布坐标系:以画布的左上角作为坐标原点
将窗口坐标系转换为画布坐标系,可以使用 canvasx() 或 canvasy() 方法:
def callback(event):
canvas = event.widget
x = canvas.canvasx(event.x)
y = canvas.canvasy(event.y)
print canvas.find_closest(x, y)
指定画布对象
Canvas 组件提供几种方法让你指定画布对象:
- Item handles, s 事实上是一个用于指定某个画布对象的整型数字(也成为画布对象的 ID)。当你在 Canvas 组件上创建一个画布对象的时候,Tkinter 将自动为其指定一个在该 Canvas 组件中独一无二的整型值。然后各种 Canvas 的方法可以通过这个值操纵该画布对象。
- Tags, 是附在画布对象上的标签,Tags 由普通的非空白字符串组成。一个画布对象可以与多个 Tags 相关联,一个 Tag 也可用于描述多个画布对象。然而,与 Text 组件不同,没有指定画布对象的 Tags 不能进行事件绑定和配置样式。也就是说,Canvas 组件的 Tags 是仅为画布对象所拥有。
- ALL(或 “all”)表示 Canvas 组件中的所有画布对象
- CURRENT (或 “current”)表示鼠标指针下的画布对象(如果有的话)
属性和方法
方法
参考小甲鱼的总结
属性
- closeenough,指定一个距离,当鼠标与画布对象的距离小于该值时,鼠标被认为在画布对象上 2. 该选项是一个浮点类型的值
- scrollregion,指定 Canvas 可以被滚动的范围, 值是一个 4 元组(x1, y1, x2, y2)表示的矩形
- confine, 指定 Canvas 组件是否允许滚动超出 scrollregion 选项指定的范围 2. 默认值是 True
- state, 设置 Canvas 的状态:NORMAL( 默认) 或 DISABLED,该值不会影响画布对象的状态
- takefocus, 指定使用 Tab 键可以将焦点移动到输入框中,默认是开启的
- Offset, 指定偏移, 值可以是:”x,y”, “#x,y”, N, NE, E, SE, S, SW, W, NW, CENTER
- 设计基本的样式
- background, bg, borderwidth, bd, 背景色和边框宽度
- height,width,高度和宽度,单位时像素
- relief, cursor,画布样式和鼠标样式
- 画布对象输入时的样式
- insertbackground,
- insertborderwidth,
- insertofftime,
- insertontime,
- insertwidth,
- 设置画布对象被选中时的样式
- selectbackground, 指定当画布对象被选中时的背景色
- selectborderwidth, 指定当画布对象被选中时的边框宽度(选中边框)
- selectforeground,指定当画布对象被选中时的前景色
- 设置获取/没有获取焦点时的样式
- highlightbackground, 指定当 Canvas 没有获得焦点的时候高亮边框的颜色
- highlightcolor,指定当 Canvas 获得焦点的时候高亮边框的颜色
- highlightthickness, 指定高亮边框的宽度
- 滚动条相关
- xscrollcommand, 与 scrollbar(滚动条)组件相关联(水平方向)
- yscrollcommand, 与 scrollbar(滚动条)组件相关联(垂直方向)
- xscrollincrement, yscrollincrement
- 指定 Canvas 水平滚动的“步长”,例如 ‘3c’ 表示 3 厘米,还可以选择的单位有 ‘i’(英寸),’m’(毫米)和 ‘p’(DPI,大约是 ‘1i’ 等于 ‘72p’)。 默认值是 0,表示可以水平滚动到任意位置
代码实例
绘制各种元素
def test1(master=None):
w = Canvas(master, width=200, height=400, bg='grey')
w.pack()
# 1. 创建各种组件
# 1.1 画线
start = {'x': 0, 'y': 50}; end = {'x': 200, 'y': 50}
line1 = w.create_line(start['x'], start['y'],
end['x'], end['y'],
fill='blue',
width=1,
capstyle=ROUND,
joinstyle=BEVEL,
)
line_tmp = w.create_line(0, 0, 200, 200, fill='red')
line2 = w.create_line(100, 0, 100, 100, fill='red', dash=(4, 4))
# 1.2 画矩形
rect1 = w.create_rectangle(50, 25, 150, 75,
fill='yellow', # 填充色
outline='hotpink', # 边框色
width=2, # 线宽
dash=(4, 10), # 虚线框
)
# 1.3 画椭圆
circle1 = w.create_oval((10, 75, 190, 155), fill='#287393')
# 1.3 画圆
circle2 = w.create_oval((0, 0, 50, 50), fill='#9370DB')
# 1.4 画多边形
poly1 = w.create_polygon((50, 0, 0, 50, 25, 100, 75, 100, 100, 50), fill='red')
# 1.5 添加文字
txt = w.create_text((90, 110), text="Hello World")
w.select_from(txt, 6)
w.select_to(txt, 10)
# 1.6 画弧线
arc1 = w.create_arc((50,10,110,110),
fill='darkblue',
extent=30,
start=90,
outline='red')
# 2. 创建的画布对象会一直存在,通过一下四个方法修改
w.coords(line1, 0, 25, 200, 25) # 用coords方法把对象移动到一个新的位置
w.itemconfig(rect1, fill='green') # 用itemconfig设置对象的选项
w.move(circle2, 75, 25) # 使用move方法移动该画布对象
w.move(poly1, 50, 155)
w.move(arc1, -50, 150)
w.delete(line_tmp) # 直接将对象的名字放进去就可以实现删除
# ALL是一个tag,表示所有的对象
# Button(master, text='删除全部对象', command=(lambda: w.delete(ALL))).pack()
Button(master, text='删除全部对象', command=(lambda x=ALL: w.delete(x))).pack()
# 3. 绑定对象,鼠标在画布上画画
def paint(event):
x1, y1 = (event.x - 1), (event.y - 1)
x2, y2 = (event.x + 1), (event.y + 1)
w.create_oval(x1, y1, x2, y2, fill="red")
w.bind("<B1-Motion>", paint)