[Tkinter 教程08] Canvas 图形绘制

python - [译][Tkinter 教程08] Canvas 图形绘制 - 个人文章 - SegmentFault 思否

一、简介

        Canvas 为 Tkinter 提供了绘图功能. 其提供的图形组件包括 线形, 圆形, 图片, 甚至其他控件. Canvas 控件为绘制图形图表, 编辑图形, 自定义控件提供了可能.
        在第一个例子里, 我们将演示如何画一条直线. create_line(coords, options) 方法用来绘制一条直线. coords 为以整形表示的四个坐标参数: x1, y1, x2, y2 . 这表示所要绘制的直线连接了 (x1, y1) 和 (x2, y2) 这两个点. 除坐标外, 该方法还接受其他可选的 options 参数. 在下面的例子里我们用 options 参数指定颜色为我们网站的主题色: fill=#476042 .
        因为是第一个例子, 所以我们尽量做了简化: 创建一个 canvas 对象然后在其上绘制一条水平直线. 这条直线将 canvas 分割为上下两部分.
        在传入坐标参数时, y = int(canvas_height / 2) 这种强制转换整形的表达式是没有必要的, 因为 create_line() 方法也接受 float 类型作为坐标参数, float 坐标数值将被自动转为整形. 下面是第一个例子的代码:

from tkinter import *
master = Tk()canvas_width = 80
canvas_height = 40
w = Canvas(master, width=canvas_width,height=canvas_height)
w.pack()y = int(canvas_height / 2)
w.create_line(0, y, canvas_width, y, fill="#476042")mainloop()

        上述代码在 Python3 下会有如下显示:

        使用 create_rectangle(coords, options) 方法可以绘制矩形. coords 参数依然表示两个点的坐标: 第一个点为左上角坐标, 第二个点为右下角坐标.

        上面的窗口是由以下示例代码生成的:

from tkinter import *master = Tk()w = Canvas(master, width=200, height=100)
w.pack()w.create_rectangle(50, 20, 150, 80, fill="#476042")
w.create_rectangle(65, 35, 135, 65, fill="yellow")
w.create_line(0, 0, 50, 20, fill="#476042", width=3)
w.create_line(0, 100, 50, 80, fill="#476042", width=3)
w.create_line(150,20, 200, 0, fill="#476042", width=3)
w.create_line(150, 80, 200, 100, fill="#476042", width=3)mainloop()

        下图阐释了上面两个例子中 create_lines() 和 create_rectangle() 这两个方法中, 用到的各个坐标的含义:

二、绘制文字

        接下来我们将说明如何在 canvas 上绘制文字. 我们将直接修改上面的例子以作为新的示例. create_text() 方法用来在 canvas 上绘制文字. 该方法的头两个参数表示所要绘制的文字的坐标. 默认情况下, 文字将以此坐标为中心进行绘制. 当然, 你也可以复写 anchor 属性来改变文字绘制的对齐方式. 比如, anchor = NW 即为指定该点坐标为所绘文字的左上角. text 属性用以指定具体绘制在 canvas 上的文字.

from tkinter import *canvas_width = 200
canvas_height = 100colours = ("#476042", "yellow")
box=[]for ratio in ( 0.2, 0.35 ):box.append( (canvas_width * ratio,canvas_height * ratio,canvas_width * (1 - ratio),canvas_height * (1 - ratio) ) )master = Tk()w = Canvas(master, width=canvas_width, height=canvas_height)
w.pack()for i in range(2):w.create_rectangle(box[i][0], box[i][1],box[i][2],box[i][3], fill=colours[i])w.create_line(0, 0,                 # canvas 原点box[0][0], box[0][1], # box[0] 的左上角坐标fill=colours[0], width=3)
w.create_line(0, canvas_height,     # canvas 的左下角坐标box[0][0], box[0][3], # box[0] 的左下角坐标fill=colours[0], width=3)
w.create_line(box[0][2],box[0][1],  # box[0] 的右上角坐标canvas_width, 0,      # canvas 的右上角坐标fill=colours[0], width=3)
w.create_line(box[0][2], box[0][3], # box[0] 的右下角坐标canvas_width, canvas_height, # canvas 的右下角坐标fill=colours[0], width=3)w.create_text(canvas_width / 2,canvas_height / 2,text="Python")
mainloop()

        虽然从代码上来看, 我们对之前的例子做了很大的改动, 但其所输出的结果却与前例相差不大, 仅仅在窗口的中间多了一个显示 "Python" 字样的方框:

        本例中我们改用变量存储坐标等参数, 这使得改动变的方便. 比如, 要将整个画布的宽高设为 90 * 190, 将 box[0] 的宽高比设为 0.3, 在本例中将很容易做到, 但在之前的例子中却要修改很多代码.
        本例运行后显示如下窗口:

三、绘制 Oval

        图形 oval 是一个蛋形的曲线. 它形似椭圆, 但并不是椭圆. 事实上, oval 这个概念没有太明确的定义. 很多不同的曲线都被叫做 oval, 他们都有如下共同点:

  • 都是可微分的简单 (非自相交) 凸闭曲线
  • 他们比椭圆曲线简单
  • 至少有一条对称轴

oval 这个词源自拉丁语中的 ovum, 意为 "蛋", 这很好的描述了它: 一条描述蛋形状的曲线. 一个 oval 由两条半径不同的弧线组成. 下图是一个特殊的 oval:

        我们可以使用如下方法在 canvas 中创建一个 oval:

id = C.create_oval ( x0, y0, x1, y1, option, ... )

        该方法的返回值为所创建的 oval 对象在当前 canvas 上的 ID.
下面的代码绘制了一个圆心在 (75, 75), 半径为 25 的正圆形:

from tkinter import *canvas_width = 190
canvas_height =150master = Tk()w = Canvas(master, width=canvas_width, height=canvas_height)
w.pack()w.create_oval(50,50,100,100)mainloop()

我们可以定义一个专门用来画正圆形的方法:

def circle(canvas, x, y, r):id = canvas.create_oval(x-r, y-r, x+r, y+r)return id

四、交互式绘图

        我们想要创建一个可在 canvas 上手动绘图的应用, 但 canvas 并未提供画单个点的方法. 我们可以通过绘制小的 oval 图形来解决这个问题:

from tkinter import *canvas_width = 500
canvas_height = 150def paint( event ):python_green = "#476042"x1, y1 = ( event.x - 1 ), ( event.y - 1 )x2, y2 = ( event.x + 1 ), ( event.y + 1 )w.create_oval( x1, y1, x2, y2, fill = python_green )master = Tk()
master.title( "Painting using Ovals" )
w = Canvas(master, width=canvas_width, height=canvas_height)
w.pack(expand = YES, fill = BOTH)
w.bind( "<B1-Motion>", paint )message = Label( master, text = "Press and Drag the mouse to draw" )
message.pack( side = BOTTOM )mainloop()

五、绘制多边形

        如果要绘制一个多边形, 可以使用 create_polygon(x0, y0, x1, y1, x2, y2, ...) 方法. 至少要传入三个点的坐标才可以绘制一个多边形.
下例用该方法绘制了一个三角形:

from tkinter import *canvas_width = 200
canvas_height =200
python_green = "#476042"master = Tk()w = Canvas(master, width=canvas_width, height=canvas_height)
w.pack()points = [0,0,canvas_width,canvas_height/2, 0, canvas_height]
w.create_polygon(points, outline=python_green, fill='yellow', width=3)mainloop()

运行后显示为如下窗口:

        或许你在读到这篇教程时圣诞节 马上就到了/为时尚早. 这里我们用 Python 和 Tkinter 做一些星星来装点我们的圣诞树. 第一课星星几乎没有用到任何编程技巧:

from tkinter import *canvas_width = 200
canvas_height =200
python_green = "#476042"master = Tk()w = Canvas(master, width=canvas_width, height=canvas_height)
w.pack()points = [100, 140, 110, 110, 140, 100, 110, 90, 100, 60, 90, 90, 60, 100, 90, 110]w.create_polygon(points, outline=python_green, fill='yellow', width=3)mainloop()

        上例非常没有技术含量. 如果我们要改变星星的大小或胖瘦, 该怎么办? 上例中我们只能重新指定所有点的坐标, 这种做法乏味且易出错. 因此, 我们用了更多的编程技巧改造了上例. 首先, 我们将星星的绘制放在一个方法体中, 并用星星的原点及两个长度指定星星的具体形状:

经过改造的代码如下:

from tkinter import *canvas_width = 400
canvas_height =400
python_green = "#476042"def polygon_star(canvas, x,y,p,t, outline=python_green, fill='yellow', width = 1):points = []for i in (1,-1):points.extend((x,          y + i*p))points.extend((x + i*t, y + i*t))points.extend((x + i*p, y))points.extend((x + i*t, y - i * t))print(points)canvas.create_polygon(points, outline=outline, fill=fill, width=width)master = Tk()w = Canvas(master, width=canvas_width, height=canvas_height)
w.pack()p = 50
t = 15nsteps = 10
step_x = int(canvas_width / nsteps)
step_y = int(canvas_height / nsteps)for i in range(1, nsteps):polygon_star(w,i*step_x,i*step_y,p,t,outline='red',fill='gold', width=3)polygon_star(w,i*step_x,canvas_height - i*step_y,p,t,outline='red',fill='gold', width=3)mainloop()

这个例子的运行结果更像一个X形. 很显然, 用逐个指定坐标点的方法绘制这个图形将无比麻烦.

六、绘制Bitmap

   create_bitmap() 方法用来绘制 bitmap. 以下 bitmap 在所有平台上都可用:
"error", "gray75", "gray50", "gray25", "gray12", "hourglass", "info", "questhead", "question", "warning"
下例将这些 bitmap 全部都绘制在一个 canvas 上:

from tkinter import *canvas_width = 300
canvas_height =80master = Tk()
canvas = Canvas(master, width=canvas_width, height=canvas_height)
canvas.pack()bitmaps = ["error", "gray75", "gray50", "gray25", "gray12", "hourglass", "info", "questhead", "question", "warning"]
nsteps = len(bitmaps)
step_x = int(canvas_width / nsteps)for i in range(0, nsteps):canvas.create_bitmap((i+1)*step_x - step_x/2,50, bitmap=bitmaps[i])mainloop()

结果如下:

七、绘制图片

        使用 create_image(x0, x0, options ...) 用来在 canvas 上绘制图片. 该方法不能直接接受图片路径等作为参数, 而是接受一个 PhotoImage 对象作为图片参数. PhotoImage 类用于读取图片, 但其只能读取 GIF 和 PGM/PPM 格式的图片.

from tkinter import *canvas_width = 300
canvas_height =300master = Tk()canvas = Canvas(master, width=canvas_width, height=canvas_height)
canvas.pack()img = PhotoImage(file="rocks.ppm")
canvas.create_image(20,20, anchor=NW, image=img)mainloop()

上面的代码运行后输出如下窗口:

八、小练习

        编写一个方法绘制一个棋盘: checkered(canvas, line_distance), 其中: "canvas" 即 Canvas 对象, 棋盘在其上绘制; "line_distance" 为线间距.

        代码如下:

from tkinter import *def checkered(canvas, line_distance):# vertical lines at an interval of "line_distance" pixelfor x in range(line_distance,canvas_width,line_distance):canvas.create_line(x, 0, x, canvas_height, fill="#476042")# horizontal lines at an interval of "line_distance" pixelfor y in range(line_distance,canvas_height,line_distance):canvas.create_line(0, y, canvas_width, y, fill="#476042")master = Tk()
canvas_width = 200
canvas_height = 100 
w = Canvas(master, width=canvas_width,height=canvas_height)
w.pack()checkered(w,10)mainloop()

上面的代码运行后输出如下窗口:


全系列:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/107657.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

视频集中存储/视频监控管理平台EasyCVR如何免密登录系统?详细操作如下

视频云存储/安防监控EasyCVR视频汇聚平台基于云边端智能协同&#xff0c;支持海量视频的轻量化接入与汇聚、转码与处理、全网智能分发、视频集中存储等。音视频流媒体视频平台EasyCVR拓展性强&#xff0c;视频能力丰富&#xff0c;具体可实现视频监控直播、视频轮播、视频录像、…

ARM Cortex-A9:裸机开发,点亮LED3

1.看原理图 外设板原理图 核心板原理图 2.在芯片手册中找到控制硬件的有效的特殊功能寄存器 选择0x1输出 GPX1DAT[0]->GPX1_0 0->1/0 3.编程 start.s Makefile复制到桌面 使用超级终端&#xff0c;连接串口 随便写一个 选择串口 配置串口 板子上电马上按enter…

vueday01——使用属性绑定+ref属性定位获取id

1.属性绑定&#xff08;Attribute 绑定&#xff09; 第一种写法 <div v-bind:id"refValue"> content </div> 第二种写法&#xff08;省略掉v-bind&#xff09; <div :id"refValue"> content </div> 2.代码展示 <template…

ROS opencv 人脸识别

人脸识别需要在输入的图像中确定人脸&#xff08;如果存在&#xff09;的位置、大小和姿态&#xff0c;往往用于生物特征识别、视频监听、人机交互等应用中。2001年&#xff0c;Viola和Jones提出了基于Haar特征的级联分类器对象检测算法&#xff0c;并在2002年由Lienhart和Mayd…

Pycharm中终端不显示虚拟环境名解决方法

文章目录 一、问题说明&#xff1a;二、解决方法&#xff1a;三、重启Pycharm 一、问题说明&#xff1a; Pycharm中打开项目配置完需要的虚拟环境后&#xff0c;在Terminal&#xff08;终端&#xff09;中无法切换及显示当前需要运行代码的虚拟环境。 比如以下一种情况&#…

SaaS系统用户权限设计

SaaS系统用户权限设计 学习目标&#xff1a; 理解RBAC模型的基本概念及设计思路 了解SAAS-HRM中权限控制的需求及表结构分析完成组织机构的基本CRUD操作 完成用户管理的基本CRUD操作完成角色管理的基本CRUD操作 组织机构管理 需求分析 需求分析 实现企业组织结构管理&#xff0…

基于 nodejs+vue网上考勤系统

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

QQd挂源码已更新最新加速项目程序全开源

1、99 公益日活动加速任务已全部完成适配&#xff0c;空间公益说说和评论并分享小世界内容任务在已有的功能上进行挂机&#xff0c; 其中【发小世界】功能暂时更名为【公益小世界】。 2、上线新功能【公益答题】用于完成参加 Qbox 公益答题任务&#xff0c;等级套装有任意一项…

高质量床上用品类网站带手机端的pbootcms模板

模板介绍&#xff1a; 这是一个基于PbootCMS内核开发的床上用品类网站模板&#xff0c;专为床上用品、家用纺织类企业设计和开发。它不仅提供了网站界面简洁简单、易于管理的特点&#xff0c;还附带了测试数据&#xff0c;方便用户进行演示和学习。 模板特点&#xff1a; 采用…

城市生命线专题周丨宏电燃气管线智慧化运营解决方案,助力燃气安全运营高质量发展

方案背景 随着我国城市发展建设速度的加快和国家能源结构的调整&#xff0c;天燃气走进了千家万户&#xff0c;燃气门站和城市燃气管网规模越来越庞大。此外&#xff0c;近年燃气泄漏导致的大型爆炸事件频发&#xff0c;给人民的生命安全和财产安全带来灾难性伤害。 行业痛点 …

c语言从入门到实战——C语言数据类型和变量

C语言数据类型和变量 前言1. 数据类型介绍1.1 字符型1.2 整型1.3 浮点型1.4 布尔类型1.5 各种数据类型的长度1.5.1 sizeof操作符1.5.2 数据类型长度1.5.3 sizeof中表达式不计算 2. signed 和 unsigned3. 数据类型的取值范围4. 变量4.1 变量的创建4.2 变量的分类 5. 算术操作符&…

黑马JVM总结(三十五)

&#xff08;1&#xff09;JMM-有序性-问题 &#xff08;2&#xff09;JMM-有序性-解决 使用maven重新编译&#xff1a; 生成两个jar包 运行这个jar包&#xff1a; 再次执行上述结果&#xff1a;0出现的次数为0了 &#xff08;3&#xff09;JMM-有序性-理解 &#xff08;4&am…

Raiden Network(二)—— Mediated transfers(多跳支付里的中介传输)

什么是Mediated transfers 在雷电网络中&#xff0c;节点可以通过中间节点进行Mediated transfers向其他节点进行支付。Mediated transfers的步骤&#xff1a; Allocation&#xff08;分配&#xff09;&#xff1a; 使用锁定的转移消息&#xff08;locked transfer message&am…

Vue-props配置功能

Vue-props配置功能 props概述 功能&#xff1a;接收从其他组件传过来的数据&#xff0c;将数据从静态转为动态注意&#xff1a; 同一层组件不能使用props&#xff0c;必须是父组件传子组件的形式。父组件传数据&#xff0c;子组件接收数据。不能什么数据都接收&#xff0c;可…

【LeetCode】29. 两数相除

1 问题 给你两个整数&#xff0c;被除数 dividend 和除数 divisor。将两数相除&#xff0c;要求 不使用 乘法、除法和取余运算。 整数除法应该向零截断&#xff0c;也就是截去&#xff08;truncate&#xff09;其小数部分。例如&#xff0c;8.345 将被截断为 8 &#xff0c;-…

新增Node.js运行环境、新增系统缓存清理功能,1Panel开源面板v1.7.0发布

2023年10月16日&#xff0c;现代化、开源的Linux服务器运维管理面板1Panel正式发布v1.7.0版本。 在这个版本中&#xff0c;1Panel新增Node.js运行环境&#xff1b;新增系统缓存清理功能&#xff1b;应用安装时支持选择远程数据库。此外&#xff0c;我们进行了40多项功能更新和…

竞赛 深度学习OCR中文识别 - opencv python

文章目录 0 前言1 课题背景2 实现效果3 文本区域检测网络-CTPN4 文本识别网络-CRNN5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习OCR中文识别系统 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;…

易天光通信推出100G BIDI ER光模块最新解决方案

随着数字信息时代的快速发展&#xff0c;网络通信技术的迅猛进步成为推动科技创新和产业升级的重要引擎之一。作为光通信行业的新秀&#xff0c;近期易天光通信推出了全新的100G BIDI ER1 Lite光模块和100G BIDI LR1 Lite光模块&#xff0c;助力崭新的未来网络建设。 易天光通…

C#网络爬虫实例:使用RestSharp获取Reddit首页的JSON数据并解析

Reddit 是一个非常受欢迎的分享社交新闻聚合网站&#xff0c;用户可以在上面发布和内容。我们的目标是抓取 Reddit 首页的数据 JSON&#xff0c;以便进一步分析和使用。 C#技术概述&#xff1a;C#是一种流行的编程语言&#xff0c;它具有流畅流畅的特点&#xff0c;非常适合开发…

centos7安装erlang23.3.4.11及rabbitmq3.9.16版本

rpm包有系统版本要求&#xff0c;el是Red Hat Enterprise Linux(EL)的缩写。 EL7是Red Hat 7.x&#xff0c;Centos 7.x EL8是Red Hat 8.x, Centos 8.x 所以我们在安装erlang及rabbitmq时需要选择与自己的服务器相对应的rpm包 # rabbitmq的rpm安装包 https://github.com/rabbi…