(九)Python 图形绘制

前述:Python程序设计可以利用多种方法实现对图像和图像的呈现和处理,在这是利用Python3.x自带的tkinter Canvas库、turtle库以及第三方的Matplotlib库进行图形的绘制的常用方法。

一、tkinter库的Canvas 图形的绘制方法

Canvas是tkinter中的画布控件,下面展示两个表:

  • Canvas 画布实例的主要属性

    属性 意义
    bg 背景色
    fg 前景色
    bitmap 背景位图
    image 底纹图像
    bd 边框宽(像素)
    with 宽度(像素)
    height 高度 (像素)
  • Canvas画布实例的主要绘图方法

    方法 功能 主要参数
    creat_arc() 给弧形和扇形 常用的参数除两点位置外,还有start(初始化角度)和 extent(中止角度)。参数fill为填充色,outline 为轮廓线色
    creat_image() 绘图像 用参数file指向图像文件,支持GIF(无动画)、PNG等格式,不支持JPG格式
    creat_line() 绘直线 两点坐标。参数arrow 为箭头样式,默认为无,FIRST或LAST分别表示箭头在首或尾。参数dash为表示虚线样式的元祖型参数。例如 dash(4,2) 表示连续4像素间隔2像素
    create_oval() 绘椭圆 用左上角和右下角两点的位置定位出矩形内切椭圆
    create_polygon() 绘多边形 顶点位置的x和y值作为参数
    create_rectangle() 绘矩形 用左上角和右下角两点的位置定位出矩形
    create_text() 文本标签 显示位置和text(文本内容)
    delete() 删除指定图形 参数为指定图形对象的名称,全部删除为ALL
  • 1.1、Canvas绘图的基本方法一:创建画布和填充颜色

    Canvas 画布的坐标原点在左上角,默认单位是像素,x轴向右为正,y轴向下为正。例如:在320x240的窗体上创建高200像素,宽280像素的画布,并填充颜色


    创建画布和填充颜色
    from tkinter import  *
    root = Tk()
    root.geometry('320x240')
    mycanvas = Canvas(root,bg='green',height=200,width=280)
    mycanvas.pack()
    btn1 = Button(root,text='关闭',command=root.destroy)
    btn1.pack()
    root.mainloop()
    
  • 1.2、Canvas绘图的基本方法一:绘制图形
    在320x240的窗体上创建高200像素,宽300像素的画布,鼠标点击画布,依次绘出:从(90,10)到(200,200)点的矩形;从(90,10)到(200,200)点的内切椭圆并填充绿色;从(90,10)到(200,200)点的内切扇形并填充粉红色;连接(20,180)、(150,10)和(290,180) 三点形成蓝色框线且无色填充的三角形;从(10,105)到(290,105)点的红色直线;以(50,10)为起点用RGB"#123456"颜色绘制文本标签“我的画布”。单击“清空”按钮删除所有图形,如下:


    绘制图形
     from tkinter import *
     root=Tk()
     root.title('绘制图形')
     root.geometry('320x240')
     def draw(event):
    
          # 画矩形
          mycnavas.create_rectangle(90,10,200,200)
          # 画椭圆,填充颜色
          mycnavas.create_oval(90,10,200,200,fill='green')
          # 画扇形
          mycnavas.create_arc(90,10,200,200,fill='pink')
          # 画多边形(三角形),前景为蓝色,无填充色
          mycnavas.create_polygon(10,180,145,10,290,180,outline='blue',fill='')
          # 画直线
          mycnavas.create_line(0,105,300,105,fill='red')
          # 写文字,颜色为十六进制RGB字符串
          mycnavas.create_text(50,10,text='我的画布',fill='#123456')
    
     def delt():
          mycnavas.delete(ALL)
    
     mycnavas = Canvas(root,width=300,height=200)
     mycnavas.pack()
     mycnavas.bind('<Button-1>',draw)  # 画布绑定鼠标点击事件
     btnclear=Button(root,text='清空',command=delt)
     btnclear.pack()
     root.mainloop()
    
  • 1.3、Canvas绘图的基本方法一:呈现位图图像

    Canvas画布支持呈现位图图像文件,文件的类型包括:GIF(无动画)、PNG等格式,但不支持JPG格式。
    在320x240的窗体上创建画布,并呈现/Users/wangchong/Desktop/呵呵.png图像。效果如下:

    呈现位图图像

    from tkinter import *
    root=Tk()
    root.title('呈现位图图像')
    root.geometry('320x240')
    mycanvas=Canvas(root)
    mycanvas.pack()
    photo=PhotoImage(file='/Users/wangchong/Desktop/呵呵.gif') # 我用的 Mac 电脑,图片的格式不要错,否则会报错的
    mycanvas.create_image(100,100,image=photo)
    root.mainloop()
    
  • 1.4、Canvas绘图的基本方法一:利用鼠标事件绘图

    利用鼠标左键移动鼠标事件,不断读取鼠标当前的位置,每次扩张1个像素绘制椭圆点,即可在画布上留下鼠标的轨迹。例如:在320x240的窗体上创建画布,并以蓝色笔创建鼠标画板。效果如下:


    利用鼠标事件绘图
    from tkinter import *
    root = Tk()
    def move(event):
         x = event.x
         y = event.y
         w.create_oval(x,y,x+1,y+1,fill='blue')
    
    w = Canvas(root,width=320,height=240)
    w.pack()
    w.bind('<B1-Motion>',move)
    root.mainloop()
    

    其中,按住鼠标左键移动的鼠标事件<B1-Motion>绑定函数move(event),当按住鼠标左键移动鼠标时,即触发读取鼠标当前位置x=event.x,y=event.y,在点(x,y)与点(x+1,y+1)组成的矩形之间留下蓝色椭圆点。

  • 1.5、Canvas画布上图型的绘制
    利用鼠标左键移动鼠标事件,不断读取鼠标当前的位置,每次扩张1个像素绘制椭圆点,即可在画布上。
    在320x240的窗体上创建画布,并以蓝色笔创建鼠标画板。如下:


    Canvas画布上图型的绘制(鼠标画板)
     from tkinter import *
     root = Tk()
     def move(event):
              x = event.x
              y = event.y
              w.create_oval(x,y,x+1,y+1,fill='blue')
    
      w = Canvas(root,width=320,height=240)
      w.pack()
      w.bind('<B1-Motion>',move)
      root.mainloop()
    

    其中,按住鼠标左键移动的鼠标事件<B1-Motion>绑定函数 move(event) ,当按住鼠标左键并移动鼠标时,即触发读取鼠标当前的位置 x=event.x,y=event.y,在点(x,y)与点(x+1,y+1)组成的矩形之间留下蓝色的椭圆点。

  • 1.6、Canvas画布上的函数图形绘制

    用create_line函数可以在画布上绘制直线,而随着变量的变化,用该方法连续绘制微直线即可得到函数的图形。
    例如:在窗体上创建320x240的画布,以画布中心为原点,用红色绘制带箭头的x和y坐标轴,用蓝色笔绘制正玄曲线y=sinx的函数图形。其中,x,y轴的放大倍数均为倍数均为40倍,即:x = 40t,t以0.01的步长在 -π~π范围内变化取值。效果如下图:

    Canvas画布上的函数图形绘制

    from tkinter import *
    import math
    root = Tk()
    w = Canvas(root,width=320,height=240)
    w.pack()
    w0 = 160  # 半宽
    h0 = 120  # 半高
    # 画红色的坐标轴线
    w.create_line(0,120,320,120,fill="red",arrow=LAST)
    w.create_line(160,240,160,0,fill="red",arrow=LAST)
    # 标题文字
    w.create_text(w0+50,10,text='y=sin(x)')
    # x轴刻度
    for i in range(-3,4):
           j=I*40
           w.create_line(j+w0,h0,j+w0,h0-5,fill="red")
           w.create_text(j+w0,h0+5,text=str(i))
    # y轴刻度
    for i in range(-2,3):
           j=I*40
           w.create_line(w0,j+h0,w0+5,j+h0,fill="red")
           w.create_text(w0-10,j+h0,text=str(-i))
    # 计算x
    def x(t):
           x=t*40  # x轴放大40倍
           x+=w0   # 平移x轴
           return x
    # 计算y
    def y(t):
           y=math.sin(t)*40  # y轴放大40倍
           y-=h0             # 平移y轴
           y=-y              # y轴值反向
           return y
    # 连续绘制微置线
    t=-math.pi
    while(t<math.pi):
         w.create_line(x(t),y(t),x(t+0.01),y(t+0.01),fill="blue")
         t+=0.01
    root.mainloop()
    

    无论函数如何复杂,以“分而治之”的计算思维原则,分别调用x(t)和y(t)函数取值绘制微直线,即可最终获得函数的图形。

二、turtle库的图形的绘制方法

turtle也是内置库 Python 图形绘制库,其绘制方法更为简单,原理如同控制一只“小龟”以不同的方向和速度进行位移而得到其运动的轨迹。turtle图形绘制的主要方法如下表:

方法 功能 备注
backward()或bk()或back() 逆箭头所指方向后退 参数为位移值
circle() 画圆 默认参数为半径,可添加参数extent(角度) 画经过这个角度的弧;可添加参数steps(n>=4的整数)画内接n边形,这两个附加参数不能同时使用
clear() 清楚所有图形但不移动光标箭头的位置 ---
color() 设置或返回颜色 以元组形式同时返回或设置笔触和填充颜色
done() 绘图完毕,结束进程 ---
dot() 画点 参数为点的大小,可附加颜色参数,如: dot(20,"blue")
fillcolor() 设置或返回填充颜色 ---
forward()或fd() 向箭头所指的方向前进 参数为位移值
goto()或setpos()或setposition() 位移至某点 参数为坐标
hideturtle()或ht() 隐藏光标箭头 ---
home() 返回原点 ---
isdown() 返回是否落笔 ---
isvisible() 返回光标箭头显示状态 ---
left()或lt() 箭头方向左转 参数为角度(不是弧度)
pencolor() 设置或返回笔触颜色 ---
pendown()或pd()down() 落笔 ---
pensize()或width() 笔触粗细 ---
penup()或pu()或up() 抬笔 ---
position()或pos() 返回当前位置坐标 ---
reset() 清楚所有图形并将光标箭头位置于原点 ---
right() 或 rt() 箭头方向右转 参数为角度(不是弧度)
setup() 初始画布窗口大小和位置 ---
setx() 水平位移至x轴坐标 ---
sety() 垂直位移至 y 轴坐标 ---
showturtle() 或 st() 显示光标箭头 ---
speed() 位移速度 ---
towards() 返回当前方向与 箭头方向之间的角度 ---
undo() 撤销(擦除)最后一步 ---
write() 绘制文本标签 默认参数为文本,可选参数为move,表示是否为动画(Ture/False)
  • 2.1、turtle绘图的基本方法

    • 2.1.1、坐标位置和方向
      setup()方法用于初始化画布窗口大小和位置,参数包括画布窗口宽、画布窗口高、窗口在屏幕的水平起始位置和窗口在屏幕的垂直起始位置。例如:setup(640,480,300,300)表示在桌面屏幕(300,300)位置开始创建640x480大小的画布窗体。用turtle创建的画布与Canvas不同,其原点(0,0)在画布的中心,坐标方向与数学定义一致,向右,向上为正。

    • 2.1.2、画笔 🖌
      方法color()用于设置或返回画笔的颜色。例如: color('red') 将颜色设为红色。也可用fillcolor()设置或返回填充颜色,或用pencolor()方法设置或返回笔触颜色。方法pensize()或width()用于设置笔触的粗细,例如:pensize(5)设置笔触为5像素粗。

    • 2.1.3、画笔控制与运动
      方法penup()、pu()或up()为抬笔,当笔触移动时不留墨迹;方法penward()、pd()或down()为落笔,当笔触移动时会留下墨迹。
      画笔的移动方向的方法有:向箭头所指的方向前进 forward()、fd()或lt();逆箭头所指方向后退backward()、bk()或back()。
      画笔的原地转角方法有:箭头方向左转left()或lt();箭头方向右转right()或rt()。
      位移至某点的方法:goto(),setpos()或setposition();画圆的方法:circle();返回原点的方法:home()。
      位移速度方法speed(),其取值返回从慢到快为1~10.注意:取0为最快(无移动过程,直接显示目标结果)。
      绘图完毕通常用方法done()结束进程。

    • 2.1.4、文字
      输出文字标签用write()方法,默认参数为输出文本,可选参数有:对齐方式 alihn(left,center,right),font元祖型字体设置(字体,字号,字形)。

    • 例如:从原点出发至坐标点(-100,100),改为红色,沿光标指向(默认方向为水平向右)前进200像素,改为蓝色,后退100像素,以动画模式输出文字(黑体,36磅,斜体)。效果如下:


      turtle绘图
      from turtle import *
      setup(640,480,300,300)
      reset()
      pensize(5)
      goto(-100,100)
      color('red')
      fd(200)
      color('blue')
      bk(100)
      write('turtle绘图',move=True,font=('黑体',36,'italic'))
      done()
      
  • 2.2、turtle图形绘图

    • 简单形状图形
      用循环结构可自动重复绘制步骤得出规则图形。
      例如:以5像素笔触重复执行“前进100像素,右转60度”的操作工6次,绘制红色正六边形了;再用circle()方法画半径为60像素的红色圆内正接六边形;然后抬笔移动至(-50,200) 点落笔,重复执行“右转144度,前进400像素”的操作共5次,绘制五角星。如下效果:

      简单形状图形

      from turtle import *
      reset()
      pensize(5)
      #画正六边形 ,每步右转60度
      for i in range(6):
             fd(100)
             right(60)
      #用circle方法画正六边形(半径为 60 像素的圆内正接六边形 )
      color('red')
      circle(60,steps=6)
      #抬笔移动位置
      up()
      goto(-50,200)
      down()
      
      # 画五角星,每步右转144度
      for i in range(5):
            right(144)
            fd(400)
      done()
      
三、Matplotlib库的图形的绘制方法

Matplotlib库是用于科学计算数据可视化的常见Python第三方模块。它借鉴了许多Matlab中的函数,可以轻松绘制高质量的线条图、直方图、饼图、散点以及误差线图等二维图形,也可以绘制三维图像,还可以方便地设定图形线条的类型、颜色、粗细以及字体的大小等属性。

  • 3.1、环境安装与基本方法
    使用 Matplotlib 绘图,需要先安装导入 numpy 科学计算模块库。如果不想经历繁琐的下载安装过程,也可使用Anaconda 等集成安装的方式来搭建科学计算环境。通常,二维图形的绘制是导入 Matplotlib的pyplot函数来完成的,首先,导入pyplot子库语句:

    import Matplotlib.pyplot as plt
    

    然后用

    plt.figure(figsize=(w,h),dpi=h)
    

    创建一个绘图对象,并设置对象的宽度比例w和高度比例h。例如:

    plt.figure(figsize=(4,3),dpi=200)
    

    为创建一个4:3的每英寸200点分别率的绘图对象,调用plt.plot()方法在绘图对象中进行绘图。
    pyplot()方法也可通过调用 subplot方法增加子图。subplot()方法通常包含三个参数:共有几行、几列、本子图是第几个子视图。例如,p1=plt.subplot(211)或p1=plt.subplot(2,1,1)表示创建第2行第1列的子视图,p1为第一个子图。
    数据可使用列表给出,plot()方法的参数通常包括x、y轴两个变量及图形的颜色、线型、数据点标记等。
    常用的颜色字符有:'r'(红色,red)、'g'(绿色,green)、'b'(蓝色,blue)、'c'(青色,cyan)、'm'(品红,magenta)、'y'(黄色,yellow)、'k'(黑色,black)、'w'(白色,white)等。
    常见的线型字符有:'_'(直线)、'_ _'(虚线)、':'(点线)、'_ .'(点划线)等。
    常用的描点标记有: '.'(点)、'0'(圆圈)、's'(方块)、'^'(三角形)、'x'(叉)、'*'(五角星)、'+'(加号) 等。
    例如:

    plt.plot(x,y,'--*r') 表示x和y两个变量绘制红色(r)虚线(--),以星号(*)作为描点标记。
    

    在同一绘制对象中可用plot()方法同时绘制多个图形,例如:

    plt.plot(x,w,'--*t',x,z,'-.+g')  表示在同一绘制对象中同时呈现x-w、x-y和x-z三组变量的图形,并且分别以蓝色实线无描点、红色虚线星描点、绿色点画线加号描点表示。
     方法plot()可使用label参数标注图例和公式。标注公式时,字符串以“$”开头和结尾,“^{}”表示上标,“cdot”表示乘号(点),在可能出现歧义的字符串时用“\”作为转义符号。
    

    注意:该字符串是以半角双引号界定的。例如:

    label="Sy=e^(-x) \cdot \cos(2\pi x)$"
    

    可表示数公式 y=(e-x)cos(2πx)。有label标注时,要用绘图对象.legend()将其显示出来。
    当需要在图上标注文本时,可以使用下列函数。
    text(): 在指定坐标位置输出文字
    xlabel(),ylabel():显示坐标轴标签文字。
    title():显示标题文字
    需要特别指出的是,在Matplotlib 默认设置中没有对应中文的支持,如果需要使用中文文本标注,应在Matplotlib 的字体管理器 font_manger 中专门设置。
    例如:将个性化字体对象 myfont设为华文宋体:

    myfont = Matplotlib.font_manger.FontProperties(fname='C:/windows/Fonts/STSONG.TTF')
    

    并在输出文字时,使用该字体属性参数:fontproperties=myfont。
    由于字体的变化,有时输出负号会影响(显示不出负号,本例并不涉及),可预设Matplotlib.rcParams['axes.unicode_minus']=False解决。
    例如:在同一绘图对象中,利用不同颜色和标注绘制折线图性。效果如下:

    import numpy as np
    import Matplotlib
    import Matplotlib.pyplot as plt
    # myfont = Matplotlib.font_manger.FontProperties\(fname='/Users/Fonts/STSONG.TTF')
    matplotlib.rcParams['axes.unicode_minus'] = False
    x=[0,1,2,4,5,6]
    w=[3,2,5,2,3,2]
    y=[1,2,3,2,4,1]
    z=[1,2,3,4,5,6]
    plt.plot(x,w,'b',x,y,'--*r',x,z,'-.+g')
    plt.xlabel("x轴",fontproperties=myfont)
    plt.ylabel("w、y、z轴",fontproperties=myfont)
    plt.title("折线图",fontsize=20,fontproperties=myfont)
    plt.show
    
  • 3.2、二维函数图形绘制

    二维函数图形的绘制可调用 numpy.linspace()方法,先生成数据系列,再用 plot() 方法绘图。通式为:

    numpy.linspace(start,stop,num=50,endpoint=True,restep=False)
    

    其中,参数依次为自变量起点、终点、生成数据点数、是否包括终点、是否返回间隔。
    例如:在同一绘图对象中,分别以红色实线和蓝色点状线绘出x在-1.7~1.7之间变化的函数图形(100个采样点),并标注其图例和对应公式:

    y=3x^3-3x^2+4sin(x)
    y=-3x^3-3x^2+4sin(x)
    

    效果如下:

    import numpy as np
    import Matplotlib.pyplot as plt
    x = np.linspace(-1.7,1.7,100)
    plt.plot(x,2*x**3-3*x**2+4*np.sin(x),"r",label="$y=3x^{3}-3x^{2}+4sin(x)$")
    plt.plot(x,-3*x**3-3*x**2+4*np.sin(x),"b.",label="$y=3x^{3}-3x^{2}+4sin(x)$")
    plt.legend()
    plt.show()
    

    函数图形的绘制也可调用numpy.arange()方法返回数据系列,再用plot()方法绘图。通式为:

    numpy.arange([start],stop[,step])
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容