【学习笔记】Windows GDI绘图(十一)Graphics详解(下)
文章目录
- Graphics的方法
- Graphics.FromImage
- SetClip设置裁切区域
- IntersectClip更新为相交裁切区域
- TranslateClip平移裁切区域
- IsVisible判断点或矩形是否在裁切区域内
- MeasureCharacterRanges测量字符区域
- MeasureString测量文本大小
- MultiplyTransform矩阵变换
Graphics的方法
Graphics.FromImage
原型:
public static System.Drawing.Graphics FromImage (System.Drawing.Image image);
作用:从图像创建Graphics对象,后续可以在该对象上绘制图形等内容。
using (var image = Image.FromFile("AIWoman.png"))
{using (var newGraphics = Graphics.FromImage(image)){newGraphics.FillEllipse(Brushes.LightGreen, new Rectangle(50, 50, 200, 200));e.Graphics.DrawImage(image, 50, 50, 600, 600);}
}
1、从图像文件创建Image对象
2、从Image对象创建Graphics对象
3、在Graphics对象上绘制圆形
4、将上面的内容绘制到当前Graphics上。
注意,不能从如下索引色图像创建Graphics对象:Format1bppIndexed、Format4bppIndexed、Format8bppIndexed,对索引色图像可使用Image.Save保存为其他格式。也不能从以下图像格式创建Graphics对象:Undefined、DontCare、Format16bppArgb1555和Format16bppGrayScale。
切记,在使用FromImage创建的Graphics对象后,要调用Dispose()方法。
SetClip设置裁切区域
原型:
public void SetClip (System.Drawing.Region region, System.Drawing.Drawing2D.CombineMode combineMode);
public void SetClip (System.Drawing.RectangleF rect, System.Drawing.Drawing2D.CombineMode combineMode);
public void SetClip (System.Drawing.Rectangle rect, System.Drawing.Drawing2D.CombineMode combineMode);
public void SetClip (System.Drawing.Graphics g, System.Drawing.Drawing2D.CombineMode combineMode);
public void SetClip (System.Drawing.RectangleF rect);
public void SetClip (System.Drawing.Rectangle rect);
public void SetClip (System.Drawing.Graphics g);
public void SetClip (System.Drawing.Drawing2D.GraphicsPath path);
public void SetClip (System.Drawing.Drawing2D.GraphicsPath path, System.Drawing.Drawing2D.CombineMode combineMode);
CombineMode枚举
值 | 说明 |
---|---|
Complement | 现有区域被排除在新区域之外 |
Exclude | 新区域被排除在现有区域之外 |
Intersect | 两个区域的相交部分 |
Replace | 新区域替换现有区域 |
Union | 两个区域的合集 |
Xor | 取只属性某一区域的合并部分 |
var values = Enum.GetValues(typeof(CombineMode)) as CombineMode[];
CombineModeIndex= (CombineModeIndex+1) % values.Length;//原裁切区域
var originRect = new Rectangle(100, 100, 200, 100);
//另一裁切区域
var newRect = new Rectangle(250, 150, 200, 100);
e.Graphics.SetClip(originRect);Region clipRegion = new Region(newRect);
e.Graphics.SetClip(clipRegion, values[CombineModeIndex]);//查看组合后的裁切区域(亮绿色部分)
e.Graphics.FillRectangle(Brushes.LightGreen,e.Graphics.VisibleClipBounds);// 重置裁切区域
e.Graphics.ResetClip();// 区域两个区域的矩形
e.Graphics.DrawRectangle(new Pen(Color.Black), originRect);
e.Graphics.DrawRectangle(new Pen(Color.Red), newRect);
e.Graphics.DrawString($"CombineMode:{values[CombineModeIndex]},亮绿区域:SetClip组合的效果", Font, Brushes.Red, new PointF(20, 20));e.Graphics.DrawString($"黑色框:原裁切区域", Font, Brushes.Black, originRect.X, originRect.Y - 20);
e.Graphics.DrawString($"红色框:另一裁切区域", Font, Brushes.Red, newRect.X, newRect.Bottom + 10);
1、获取CombineMode的各枚举值
2、定义两个矩形,一个设为当前裁切区域,另一个为组合区域,测试不同CombineMode的值的效果
3、在重置裁切区域,将两个区域的矩形绘制显示,方便观察效果。
IntersectClip更新为相交裁切区域
原型:
public void IntersectClip (System.Drawing.Rectangle rect);
public void IntersectClip (System.Drawing.RectangleF rect);
public void IntersectClip (System.Drawing.Region region);
作用:将当前裁切区域更新为与指定区域的交集。
TranslateClip平移裁切区域
原型:
public void TranslateClip (int dx, int dy);
public void TranslateClip (float dx, float dy);
作用:平移裁切区域
//原裁切区域
var originRect = new Rectangle(100, 100, 200, 100);
//另一裁切区域
var newRect = new Rectangle(250, 150, 200, 100);
e.Graphics.SetClip(originRect);Region clipRegion = new Region(newRect);
e.Graphics.IntersectClip(clipRegion);//查看组合后的裁切区域(亮绿色部分)
e.Graphics.FillRectangle(Brushes.LightGreen, e.Graphics.VisibleClipBounds);
//平移裁切区域亮蓝部分)
e.Graphics.TranslateClip(50, 50);
e.Graphics.FillRectangle(Brushes.LightBlue, e.Graphics.VisibleClipBounds);
// 重置裁切区域
e.Graphics.ResetClip();// 区域两个区域的矩形
e.Graphics.DrawRectangle(new Pen(Color.Black), originRect);
e.Graphics.DrawRectangle(new Pen(Color.Red), newRect);e.Graphics.DrawString($"IntersectClip方法,与SetClip的Intersect相同,亮绿部分", Font, Brushes.Red, new PointF(20, 20));
e.Graphics.DrawString($"平移后裁切区域,亮蓝部分", Font, Brushes.Red, new PointF(20, 35));
e.Graphics.DrawString($"黑色框:原裁切区域", Font, Brushes.Black, originRect.X, originRect.Y - 20);
e.Graphics.DrawString($"红色框:另一裁切区域", Font, Brushes.Red, newRect.X, newRect.Bottom + 10);
IntersectClip等同于SetClip方法的参数为CombineMode.Intersect时的效果。
IsVisible判断点或矩形是否在裁切区域内
原型:
public bool IsVisible (System.Drawing.Point point);
public bool IsVisible (System.Drawing.PointF point);
public bool IsVisible (System.Drawing.Rectangle rect);
public bool IsVisible (System.Drawing.RectangleF rect);
public bool IsVisible (int x, int y);
public bool IsVisible (float x, float y);
public bool IsVisible (int x, int y, int width, int height);
public bool IsVisible (float x, float y, float width, float height);
作用:判断一个点或一个矩形是否在裁切区域内(相交也算在区域内)
[System.ComponentModel.Description("Graphics的IsVisible方法")]
public void Demo11_04(PaintEventArgs e)
{//原裁切区域var clipRect = new Rectangle(100, 100, 200, 200);e.Graphics.SetClip(clipRect);e.Graphics.FillRectangle(Brushes.LightGreen, e.Graphics.VisibleClipBounds);//注意,这里的宽、高要减1e.Graphics.DrawRectangle(Pens.Red, clipRect.X, clipRect.Y, clipRect.Width - 1, clipRect.Height - 1);//区域外var ptA = new Point(80, 80);var isPtAVisiable = e.Graphics.IsVisible(ptA);//区域内var ptB = new Point(120, 120);var isPtBVisiable = e.Graphics.IsVisible(ptB);//边上,也算区域内var ptC = new Point(100, 100);var isPtCVisiable = e.Graphics.IsVisible(ptC);//另一边要减1,所以这里不算var ptD = new Point(clipRect.X + clipRect.Width, clipRect.Y + clipRect.Height);var isPtDVisiable = e.Graphics.IsVisible(ptD);var rectA = new Rectangle(320, 80, 50, 50);var isRectAVisiable = e.Graphics.IsVisible(rectA);var rectB = new Rectangle(180, 180, 50, 50);var isRectBVisiable = e.Graphics.IsVisible(rectB);var rectC = new Rectangle(280, 280, 50, 50);var isRectCVisiable = e.Graphics.IsVisible(rectC);var clipBounds = e.Graphics.ClipBounds;e.Graphics.ResetClip();DrawPointIsVisiable(e, ptA, isPtAVisiable);DrawPointIsVisiable(e, ptB, isPtBVisiable);DrawPointIsVisiable(e, ptC, isPtCVisiable);DrawPointIsVisiable(e, ptD, isPtDVisiable);DrawRectIsVisiable(e, rectA, isRectAVisiable);DrawRectIsVisiable(e, rectB, isRectBVisiable);DrawRectIsVisiable(e, rectC, isRectCVisiable);e.Graphics.DrawString($"有效裁切区域:({clipBounds.X},{clipBounds.Y},{clipBounds.Width},{clipBounds.Height})", Font, Brushes.Red, new Point(20, 20));
}//显示点是否可见
private void DrawPointIsVisiable(PaintEventArgs e, Point pt, bool isVisable)
{e.Graphics.FillEllipse(Brushes.Red, pt.X - 3, pt.Y - 3, 6, 6);e.Graphics.DrawString($"Pt({pt.X},{pt.Y}),是否可见:{isVisable}", Font, Brushes.Red, pt.X + 10, pt.Y);
}//显示矩形是否可见
private void DrawRectIsVisiable(PaintEventArgs e,Rectangle rect,bool isVisable)
{e.Graphics.DrawRectangle(Pens.Blue, rect);e.Graphics.DrawString($"Rect({rect.X},{rect.Y},{rect.Width},{rect.Height}),是否可见:{isVisable}", Font, Brushes.Blue, rect.Right + 10, rect.Y);
}
1、分别测试点在区域外、区域边缘、区域内的情况
2、分别测试矩形在区域外、区域相交、区域内的情况
MeasureCharacterRanges测量字符区域
原型:
public System.Drawing.Region[] MeasureCharacterRanges (string text, System.Drawing.Font font, System.Drawing.RectangleF layoutRect, System.Drawing.StringFormat stringFormat);
作用:给定一个文字绘制布局(需够长足以绘制文字),测量相应的文字的绘制范围。
// 设置一段文字
string measureString = "Hello,这是一段测试范围的文字";
using (Font stringFont = new Font("宋体", 16.0F))
{// 设置"Hello","测试范围"的字符范围CharacterRange[] characterRanges = { new CharacterRange(0, 5), new CharacterRange(10, 4) };// Create rectangle for layout.float x = 50.0F;float y = 50.0F;float width = 75.0F;float height = 500.0F;//注意,这个范围要能完整含文字在RectangleF layoutRect = new RectangleF(x, y, width, height);e.Graphics.DrawRectangle(Pens.LightGreen, Rectangle.Round(layoutRect));// 设置文字格式StringFormat stringFormat = new StringFormat();stringFormat.FormatFlags = StringFormatFlags.DirectionVertical;stringFormat.SetMeasurableCharacterRanges(characterRanges);// 绘制文字e.Graphics.DrawString(measureString, stringFont, Brushes.Black, x, y, stringFormat);// 绘制两个文字的区域Region[] stringRegions = e.Graphics.MeasureCharacterRanges(measureString,stringFont, layoutRect, stringFormat);// 绘制第一个文字区域RectangleF measureRect1 = stringRegions[0].GetBounds(e.Graphics);e.Graphics.DrawRectangle(new Pen(Color.Red, 1), Rectangle.Round(measureRect1));// 绘制第二个文字区域RectangleF measureRect2 = stringRegions[1].GetBounds(e.Graphics);e.Graphics.DrawRectangle(new Pen(Color.Blue, 1), Rectangle.Round(measureRect2));
}
1、定义一段要测量的文字“Hello,这是一段测试范围的文字”,其中要测试"Hello"与"测试范围"两个字符串区域
2、定义文字绘制矩形布局
3、绘制文字
4、测量文字的范围
5、将测量范围用两个矩形框绘制到文字处。
MeasureString测量文本大小
原型:
public System.Drawing.SizeF MeasureString (string text, System.Drawing.Font font);
public System.Drawing.SizeF MeasureString (string text, System.Drawing.Font font, System.Drawing.SizeF layoutArea);
public System.Drawing.SizeF MeasureString (string text, System.Drawing.Font font, int width);
public System.Drawing.SizeF MeasureString (string text, System.Drawing.Font font, System.Drawing.PointF origin, System.Drawing.StringFormat stringFormat);
public System.Drawing.SizeF MeasureString (string text, System.Drawing.Font font, System.Drawing.SizeF layoutArea, System.Drawing.StringFormat stringFormat);
public System.Drawing.SizeF MeasureString (string text, System.Drawing.Font font, int width, System.Drawing.StringFormat format);
public System.Drawing.SizeF MeasureString (string text, System.Drawing.Font font, System.Drawing.SizeF layoutArea, System.Drawing.StringFormat stringFormat, out int charactersFitted, out int linesFilled);
作用:测量文本的范围,或限制宽度时,可自动计算行换后的高度,也统计字符个数,行数。
//设置文本和字体
string measureString = "待测试的文字还包含English";
Font stringFont = new Font("宋体", 16);//测量文本大小
var stringSize = e.Graphics.MeasureString(measureString, stringFont);
var insertPt = new PointF(20, 20);
//绘制文本大小的矩形
e.Graphics.DrawRectangle(new Pen(Color.Red, 1), insertPt.X, insertPt.Y, stringSize.Width, stringSize.Height);
//绘制文本
e.Graphics.DrawString(measureString, stringFont, Brushes.Black, insertPt);e.Graphics.TranslateTransform(100, 100);
// Set point for upper-left corner of string.
float x = 50.0F;
float y = 50.0F;
PointF ulCorner = new PointF(x, y);// Set string format.
StringFormat newStringFormat = new StringFormat();
newStringFormat.FormatFlags = StringFormatFlags.DirectionVertical;// Measure string.
stringSize = e.Graphics.MeasureString(measureString, stringFont, ulCorner, newStringFormat);// Draw rectangle representing size of string.
e.Graphics.DrawRectangle(new Pen(Color.Red, 1), x, y, stringSize.Width, stringSize.Height);// Draw string to screen.
e.Graphics.DrawString(measureString, stringFont, Brushes.Black, ulCorner, newStringFormat);e.Graphics.TranslateTransform(100, 0);// Set maximum layout size.
var layoutSize = new SizeF(100.0F, 300.0F);// Set string format.
newStringFormat.FormatFlags = StringFormatFlags.DirectionVertical;// Measure string.
stringSize = e.Graphics.MeasureString(measureString, stringFont, layoutSize, newStringFormat);// Draw rectangle representing size of string.
e.Graphics.DrawRectangle(new Pen(Color.Red, 1), 0.0F, 0.0F, stringSize.Width, stringSize.Height);// Draw string to screen.
e.Graphics.DrawString(measureString, stringFont, Brushes.Black, new PointF(0, 0), newStringFormat);e.Graphics.TranslateTransform(100, 0);// Set maximum width of string.
int stringWidth = 100;// Set string format.
newStringFormat.FormatFlags = StringFormatFlags.DirectionVertical;// Measure string.
stringSize = e.Graphics.MeasureString(measureString, stringFont, stringWidth, newStringFormat);// Draw rectangle representing size of string.
e.Graphics.DrawRectangle(new Pen(Color.Red, 1), 0.0F, 0.0F, stringSize.Width, stringSize.Height);// Draw string to screen.
e.Graphics.DrawString(measureString, stringFont, Brushes.Black, new PointF(0, 0), newStringFormat);//============
e.Graphics.TranslateTransform(100, 0);
// Set maximum layout size.
layoutSize = new SizeF(100.0F, 300.0F);// Set string format.
newStringFormat.FormatFlags = StringFormatFlags.DirectionVertical;// Measure string.
int charactersFitted;
int linesFilled;
stringSize = e.Graphics.MeasureString(measureString, stringFont, layoutSize, newStringFormat, out charactersFitted, out linesFilled);// Draw rectangle representing size of string.
e.Graphics.DrawRectangle(new Pen(Color.Red, 1), 0.0F, 0.0F, stringSize.Width, stringSize.Height);// Draw string to screen.
e.Graphics.DrawString(measureString, stringFont, Brushes.Black, new PointF(0, 0), newStringFormat);// Draw output parameters to screen.
string outString = "chars " + charactersFitted + ", lines " + linesFilled;
e.Graphics.DrawString(outString, stringFont, Brushes.Black, new PointF(100, 0));
测试不同参数下测量文本区域的结果。
MultiplyTransform矩阵变换
原型:
public void MultiplyTransform (System.Drawing.Drawing2D.Matrix matrix);//默认是MatrixOrder.Prepend
public void MultiplyTransform (System.Drawing.Drawing2D.Matrix matrix, System.Drawing.Drawing2D.MatrixOrder order);
作用:将世界变换矩阵与该矩形相乘。
var rect = new Rectangle(0, 0, 200, 100);
var pt1 = new Point(0, 0);
var pt2 = new Point(200, 100);
// Create transform matrix.
using (Matrix transformMatrix = new Matrix())
{//平移(200,100)transformMatrix.Translate(200.0F, 100.0F);//世界坐标顺时旋转30度e.Graphics.RotateTransform(30.0F);e.Graphics.DrawLine(Pens.Red, pt1, pt2);e.Graphics.DrawEllipse(new Pen(Color.Blue, 3), rect);//先平移,再旋转e.Graphics.MultiplyTransform(transformMatrix);//默认是 MatrixOrder.Prepend在e.Graphics.DrawLine(Pens.Blue, pt1, pt2);// Draw rotated, translated ellipse.e.Graphics.DrawEllipse(new Pen(Color.Blue, 3), rect);e.Graphics.ResetTransform();//世界坐标顺时旋转30度e.Graphics.RotateTransform(30.0F);//先旋转,再平移e.Graphics.MultiplyTransform(transformMatrix, MatrixOrder.Append);e.Graphics.DrawLine(Pens.Red, pt1, pt2);e.Graphics.DrawEllipse(new Pen(Color.Red, 3), rect);
}
分别测试应用矩阵顺序不同,导致的结果不同。
相关文章:

【学习笔记】Windows GDI绘图(十一)Graphics详解(下)
文章目录 Graphics的方法Graphics.FromImageSetClip设置裁切区域IntersectClip更新为相交裁切区域TranslateClip平移裁切区域IsVisible判断点或矩形是否在裁切区域内MeasureCharacterRanges测量字符区域MeasureString测量文本大小MultiplyTransform矩阵变换 Graphics的方法 Gr…...

win10环境下nodejs安装过程
打开 https://nodejs.org/en/官网下载node.js 2.下载完成后的安装文件为node-v16.16.0-x64.msi,双击进行安装即可。 3.一直默认安装,记得可以更改安装路径 4.其他不用打勾,一直next,安装完成即可。 5.安装完成后,wi…...
亚信安慧AntDB:卓越的拓展性和灵活性
在当今这个信息爆炸的时代,企业对数据处理的需求不断增长,传统的数据库系统往往难以应对海量数据的存储和处理挑战。然而,随着亚信安慧AntDB的出现,解决这一难题的曙光终于出现在眼前。AntDB不仅仅具备了高吞吐、高并发、高性能的…...

【计算机毕设】基于SpringBoot的中小企业设备管理系统设计与实现 - 源码免费(私信领取)
免费领取源码 | 项目完整可运行 | v:chengn7890 诚招源码校园代理! 1. 研究目的 在中小企业中,设备管理是确保生产和运营效率的重要环节。传统的设备管理通常依赖于手工记录和人工管理,容易导致数据不准确、…...
每日一练 - BGP配置中的认证方法
01 真题题目 在 BGP 配置中使用认证,应该如何配置? A.一对 BGP 对等体之间必频使用相同的 MD5 PASSWORD B.同一个 AS 内的所有路由器都必须使用相同的 password C.一台路由器上的所有 BGP 对等体都必频使用相同的 password D.一对 BGP 对等体之间必须使用相同的明文 passwo…...
人机交互中的阴差阳错
人机交互是一门研究系统与用户之间的交互关系的学问。它旨在设计和实现使人们能够与计算机系统进行有效交互的方法和技术。人机交互领域研究的热门话题之一就是人工智能。另一个热门话题就是增强现实(Augmented Reality)和虚拟现实(Virtual R…...

个人网站建设方案书
个人网站建设方案书 一、项目背景 随着互联网的迅猛发展,个人网站已经成为展示个人能力、情感表达的重要平台。无论是个人品牌推广,还是个人作品展示,个人网站都能够为个人提供一个独特的展示空间。因此,建设一个个人网站已经成为…...

IIS7整合Tomcat9服务器,并搭建ASP+PHP+JSP完整运行环境
本文以Windows Vista系统为例,详细讲解IIS7整合Tomcat服务器,同时支持ASPPHPJSP三种Web动态网页技术的方法。 Vista系统自带的IIS版本为7.0,能安装的IE浏览器的最高版本为IE9。IE9也是Vue2前端框架支持的最低浏览器版本。 【准备工作】 去微…...
IT运维重难点剖析及应对策略
运维工作作为信息技术领域的重要组成部分,对于保障企业信息系统的稳定运行具有至关重要的作用。然而,在实际工作中,运维人员常常面临各种重难点问题,这些问题不仅影响运维效率,还可能对企业的正常运营造成不利影响。本…...
【Python学习】面向对象(OOP)
让我们从Python面向对象编程(OOP)的基础概念开始,逐步深入到继承、多态、特殊方法和运算符重载。 一、类和对象 什么是类和对象? - 类(Class):类是创建对象的蓝图或模板。它定义了一组属性和方法…...

鸿蒙HarmonyOS实战—如何使用Video组件播放视频
1.视频播放 鸿蒙系统中,关于视频播放,可以使用上层视频组件Video。 参数如下 src 支持file:///data/storage路径前缀的字符串,用于读取应用沙箱路径内的资源。需要保证目录包路径下的文件有可读权限。 说明:视频支持的格式是&am…...
【Paddle2ONNX】为 Paddle2ONNX 升级自适应ONNX IR Version功能
1 简介 最近在浏览 Paddle2ONNX 的 Issues 时,我发现有用户需要让 Paddle2ONNX 支持导出的 ONNX 模型根据opset版本自适应 ONNX IR 版本,于是我动手添加了这个功能。 能否指定 IR representation的版本 Issue #1248 PaddlePaddle/Paddle2ONNX 2 什么…...
JS 中的DOM 操作
目录 概念Node接口NodeList接口,HTMLCollection接口ParentNode接口,ChildNode接口Document节点Element节点属性的操作Text节点和DocumentFragment节点CSS操作Mutation Observer API概念 D...

短剧出海怎么做?
短剧出海,即是指将制作的短剧内容推广到国际市场,吸引海外观众。以下是一些策略和步骤,可以帮助你实现这一目标: 研究目标市场:了解你想要进入的海外市场的文化、偏好和消费习惯。这包括语言、流行文化、媒体消费习惯等…...

【C++修行之道】类和对象(四)运算符重载
目录 一、 运算符重载 函数重载和运算符重载有什么关系? 二、.*运算符的作用 三、运算符重载的正常使用 四、重载成成员函数 五、赋值运算符重载 1.赋值运算符重载格式 传值返回和引用返回 有没有办法不生成拷贝? 2. 赋值运算符只能重载成类的…...

伯克希尔也被ST?
地球(最)贵股票突然闪崩,美股故障再次上演。昨晚齐刷刷一片的美股出现行情异常,伯克希尔、蒙特利尔银行、巴里克黄金等股票股价跌幅超过98%。其中,巴菲特旗下伯克希尔哈撒韦A类股股价更是暴跌99.97%,股价从…...

低代码和零代码软件时代质量管理(QM)和质量管理系统(QMS)
【前言】 质量控制过程的目的是为了确保产品的制造标准得到保持和改进。质量控制过程使公司能够满足客户的期望,同时确保产品质量的一致水平。采用这些标准创造了一种公司文化,鼓励所有员工努力实现高质量的生产标准。低代码和零代码软件可以成为质量控…...
JS跨页面或跨JS文件对变量赋值
JS跨页面或跨JS文件对变量赋值,这是很小的一个问题。 但问题虽小,却总觉得有点不够自然,不爽。 为什么呢?访问一个页面上的变量不是什么难事,比如用parent.变量名,或者windows名.变量名,都可以…...

xxe漏洞——无回显(ctfshow web374——378)
ctfshow——web374 <?php/* # -*- coding: utf-8 -*- # Author: h1xa # Date: 2021-01-07 12:59:52 # Last Modified by: h1xa # Last Modified time: 2021-01-07 13:36:47 # email: h1xactfer.com # link: https://ctfer.com*/error_reporting(0); libxml_disable_en…...
深入解读 Android Hook 技术-从原理到实践
在Android开发中,Hook技术是一种强大的手段,它允许开发者拦截和修改系统或应用的行为。通过Hook,我们可以在事件传递的过程中插入自定义的逻辑,从而实现对应用行为的监控和修改。 Android 系统有自己的事件分发机制,…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...