在Python的tkinter库中,如何使用画布功能来绘制函数图像的具体步骤
最编程
2024-07-28 13:35:33
...
非计算机专业准备备考二级,然后今天刚学到tkinter.canvas模块,看到书中的正弦函数绘制,在基础上进行改进,通过改变全局的一些初始变量实现了函数图像的放大缩小,位置移动等功能。在这里做个保存!
参考教材 - Python程序设计基础(第二版)李东方 (ISBN:978 7121 376054) [例9-6]
import math
import tkinter
# 增加了设置画布大小,设置坐标位置,设置x, y比例长度, 设置图像精度以及设置绘制的函数
canvas_x = 320 # 画布x轴像素长度
canvas_y = 240 # 画布y轴像素长度
origin = (10, 120) # 原点的x, y像素值 - 原点中心值为(160, 120)
unit_length_x = 20 # 坐标轴中x的比例长度
unit_length_y = 40 # 坐标轴中y的比例长度
curve_precision = 0.01 # 曲线的画图精度,可以理解为Δx - 经过测试,一般0.01即可
fun_text = 'y=sin(x)' # 绘制的函数
coordinate_x = origin[1] # 坐标轴 x (在y轴上的)的位置
coordinate_y = origin[0] # 坐标轴 y (在x轴上的)的位置
def calc_x(t):
# 通过传入的数据为坐标轴的位置,因此进行一个坐标轴 - 像素点转换,然后返回
num_x = t * unit_length_x
# num_x += canvas_x/2
# 由于坐标轴位置变化,所以对应的也要变化
num_x += coordinate_y
return num_x
def calc_y(t):
# 通过数学计算计算出对应的y值,然后进行坐标轴 - 像素点转换
num_y = math.sin(t) * unit_length_y # 先放大
# 由于y轴与x轴不同,y轴的正坐标方向与像素的正坐标方向是相反的
# 所以首先将其翻转一下,然后在向下平移
num_y = -num_y
# num_y += canvas_y / 2
# 由于坐标轴位置变化,所以对应的也要变化
num_y += coordinate_x
return num_y
if __name__ == '__main__':
root = tkinter.Tk()
mycanvas = tkinter.Canvas(root, width=canvas_x, height=canvas_y)
mycanvas.pack()
# 绘制坐标轴横线
# mycanvas.create_line(0, canvas_y/2, canvas_x, canvas_y/2, fill='red', arrow=tkinter.LAST)
# mycanvas.create_line(canvas_x/2, canvas_y, canvas_x/2, 0, fill='red', arrow=tkinter.LAST)
# 由于改变了坐标轴位置,所以坐标轴也要改变
mycanvas.create_line(0, coordinate_x, canvas_x, coordinate_x, fill='red', arrow=tkinter.LAST)
mycanvas.create_line(coordinate_y, canvas_y, coordinate_y, 0, fill='red', arrow=tkinter.LAST)
# 绘制坐标轴刻度
# range(a, b)的计算方法:
# # 首先明确 a 和 b 代表的是坐标轴的刻度
# # 其次总长度为 x=320, y=240
# # 由于40为一个单位,所以x轴可以分为320/40 = 8份,也就是7个坐标轴。y轴可以分为240/40=6份也就是5个坐标轴
# # 因此x轴坐标刻度为[-8/2+1, 8/2),y轴坐标刻度为[-6/2+1, 6/2)
# # x:range( (-canvas_x/unit_length_x) / 2 + 1, (canvas_x/unit_length_x) / 2)
# # x:range( (-canvas_y/unit_length_y) / 2 + 1, (canvas_y/unit_length_y) / 2)
#
# for i in range( math.ceil((-canvas_x/unit_length_x) / 2) + 1, math.ceil((canvas_x/unit_length_x) / 2)):
# # 由于计算出来的 i 并不是实际画布像素值,所以要乘上unit_length_x
# j = i*unit_length_x # 坐标轴放大40倍
# # 对于 i*unit_length_x即是获得了实际的坐标轴对应的放大40倍后的值,但是这个值并不是真正的像素点
# # 由于我们是以中心点(canvas/x, canvas_y)为原点的,因此我们要在这里加上对应的原点像素值才能得到真正的坐标轴对应的像素点
# mycanvas.create_line(j+canvas_x/2, canvas_y/2, j+canvas_x/2, canvas_y/2-5, fill='red')
# mycanvas.create_text(j+canvas_x/2, canvas_y/2+10, text=i)
# for i in range( math.ceil((-canvas_y/unit_length_y) / 2) + 1, math.ceil((canvas_y/unit_length_y) / 2)):
# j = i*unit_length_y # 坐标轴放大40倍
# mycanvas.create_line(canvas_x/2, j+canvas_y/2, canvas_x/2+5, j+canvas_y/2, fill='red')
# mycanvas.create_text(canvas_x/2-10, j+canvas_y/2, text=-i)
# 因为增加了坐标轴的位置,因此上述理论推翻
# 首先明确,x轴的轴正坐标像素长度应该为:canvas_x - coordinate_y
# 因此负半轴像素值为:canvas_x - (canvas_x - cordinate_y)也就是cordinate_y
# 此处的算法应该改为range*( -(coordinate_y / unit_length_x) + 1, ((canvas_x-coordinate_y) / unit_length_x)) )
for i in range( -math.ceil((coordinate_y / unit_length_x)) + 1, math.ceil((canvas_x-coordinate_y) / unit_length_x)):
print(i)
j = i*unit_length_x
# 对于 i*unit_length_x即是获得了实际的坐标轴对应的放大unit_length倍后的值,但是这个值并不是真正的像素点
# 由于我们是以中心点(coordinate_y, coordinate_x)为原点的,因此我们要在这里加上对应的原点像素值才能得到真正的坐标轴对应的像素点
mycanvas.create_line(j+coordinate_y, coordinate_x, j+coordinate_y, coordinate_x-5, fill='red')
mycanvas.create_text(j+coordinate_y, coordinate_x+10, text=i)
# 同理由于y轴是相反的,所以正半轴为:cordinate_x,负半轴为canvas_y - cordinate_x
# 此处的算法应该改为range*( -(canvas_y - coordinate_x) / unit_length_y) + 1, (cordinate_x / unit_length_y)) )
for i in range( -math.ceil((canvas_y - coordinate_x) / unit_length_y) + 1, math.ceil((coordinate_x / unit_length_y))):
print(i)
j = i*unit_length_y
# 对于 i*unit_length_y即是获得了实际的坐标轴对应的放大unit_length倍后的值,但是这个值并不是真正的像素点
# 由于我们是以中心点(coordinate_y, coordinate_x)为原点的,因此我们要在这里加上对应的原点像素值才能得到真正的坐标轴对应的像素点
mycanvas.create_line(coordinate_y, j+coordinate_x, coordinate_y+5, j+coordinate_x, fill='red')
mycanvas.create_text(coordinate_y-10, j+coordinate_x, text=i)
# 绘制函数名称 - 位置在y轴右上方
mycanvas.create_text(coordinate_y + 50, 10, text=fun_text)
# 此处的-3是坐标轴的最低值,3是坐标轴的最大值
# 此处我们仅将坐标轴的值传入函数,然后通过函数输出一个对应的像素值
# 通过改变坐标轴的值(从坐标轴的最小值一直到坐标轴的最大值,每次增加curve_precision)
# draw_point = math.ceil((-canvas_x/unit_length_x) / 2) + 1
# while draw_point < math.ceil((canvas_x/unit_length_x) / 2) - 1:
# 由于坐标轴位置改变,所以对应的值要改变
draw_point = -math.ceil((coordinate_y / unit_length_x)) + 1 # 此处为x轴负半轴
while draw_point < math.ceil((canvas_x-coordinate_y)) - 1: # 此处为x轴正半轴
mycanvas.create_line(calc_x(draw_point), calc_y(draw_point), calc_x(draw_point+0.01), calc_y(draw_point+0.01), fill='blue')
draw_point += curve_precision
root.mainloop()