Cocoa 图形开发基础

65 篇文章 0 订阅
47 篇文章 0 订阅

Cocoa图形介绍

在本系列前一阶段,我主要讨论了如何使用Cocoa来编写用户界面。我还介绍了面向对象编程(OOP)的基本概念,以及在程序中最经常使用的Cocoa类。今

天,我们开始把重点转向Cocoa的画图和二维图形处理上。我们今天会做一个小小的起步,讨论如何在窗口中绘制简单的图形

在以后的章节中,我将会涉及绘制更复杂的图形,实现动画,以及处理原始图象数据。在此之前,让我们从最基本开始

矩形,大小和点

矩形,大小和点代表了三种Cocoa的数据类型,其实不过是C的结构而已。他们分别是NSRect,NSSize,和NSPoint。

NSPoint(或者简单说,一个“点”),是三种数据类型中最基本的,所以我们先讨论它。Cocoa中的一个点是存储了一对坐标的变量,它是用x和y值来表示点

在我们绘图平面中的坐标。我们迟些会更深入地讨论绘图平面,不过平面的意思是我们绘图的面的坐标系是笛卡儿坐标系,这我们应该在几何学中学过。平面

的原点(0, 0)在你绘图平面的左下角,正的x值表示在它的右方,正的y值表示在它的上方。在这个系统中,一个距离单位为你屏幕上的一个象素,记住这一

点,以便以后可以想象你画的图在屏幕上的大小。

好,那点究竟是怎么样?在Cocoa中怎么表示他们?NSPoint是一个C的结构,它的定义是:

typedef struct _NSPoint{

float x;

float y;

} NSPoint;

如果你对C不熟悉的话,下面是简单的解释。typedef语句是定义一种新的数据类型,NSPoint,它和_NSPoint这个结构类型是一样的。所以,当我们说

到NSPoint的时候,就相当于说到上面的这个结构。如果你对C的结构不熟悉,那么你最好能够看看你喜欢的C的介绍,以获得一些这方面的知识。

要初始化一个NSPoint变量,我们使用一个基础库的函数NSMakePoint。它有两个参数,分别代表一个点的x值和y值,并返回一个按这两个值初始化

的NSPoint变量。下面的一行代码显示如何使用:

NSPoint p = NSMakePoint (10, 45) ;

要使用这些变量(NSPoint,NSRect和NSSize),你要知道如何访问结构的成员。换句话说,给定一个NSPoint变量,我们怎么决定这个点的x坐标和y坐标

呢?答案是句点操作符。句点操作符用!!"量.成#名称的语法来访问结构中的成员。

例如,如果你想从一个NSPoint结构变量中获得x和y坐标值,我们可以按下面的办法做:

float xCoord = p.x;

float yCoord = p.y;

如果是按照我们前面说的那个点,那么xCoord的值是“10”,yCoord的值是“45”。现在我们讲完NSPoint了,让我们看看NSRect和NSSize,他们是我们会经

常用到的另外两个数据类型。

NSRect

NSRect(或者简单地说,“矩形”)是在基础框架中定义的另外一个数据类型。“矩形”在画图区中定义了一个矩形区域。它不属于一种图形,但它定义一个图形

的я界。比如说,窗口的я界,绘图区的я界,填充颜色的区域或其它类似的东西。矩形由它的原点和大小所决定,大小其实就是它的宽和高。在基础库使用

指南中关于NSRect的正式定义是:

typedef struct _NSRect {

NSPoint origin;

NSSize size;

} NSRect;

origin是一个NSPoint类型的对象,它指明了矩形的左下角位置。NSSize是一个简单的结构,其成员是矩形的宽和高数值。NSSize的定义如下:

typedef struct _NSSize {

float width;

float height;

} NSSize;

要创建一个矩形,我们使用基础库函数NSMakeRect,它有四个参数:原点的x和y坐标,宽度,高度。如果我们想要创建一个NSRect变量,我们可以这样做

NSRect r = NSMakeRect(10, 10, 100, 150);

这会创建一个原点为(10, 10),宽100,高150的矩形。这样的话,矩形的右上角将是点(110, 160)。

由于NSRect的成员也是结构变量,所以我们要使用两次句点操作符来访问到矩形的最底层信息。例如,要获得我们上面创建的矩形的x坐标值,我们要这样做

float xOrigin = r.origin.x;如果我们要知道矩形的高,我们可以类似地这么做:

float width = r.size.width;

在我们掌握了关于Cocoa绘图中数据类型的基本知识以后,让我们看看如何绘制图形。

画布和画刷

明白Cocoa绘图原理的一种有用的方法是想象你是怎么画画的。你要有一个来画东西上去,同时你需要一个东西来画——换句话说,就是一张画布和一支画

笔。在Cocoa中,画布就是NSView类,画笔就是NSBezierPath类。让我们先看看如何在PB和IB中设置我们的画布,然后我们在深入到真正画画的有趣部

分。

设置画布

正如我们前面说过的,Cocoa的画布是NSView类。它提供定义屏幕上画图区域,以及绘图背后所需要的机制。NSView是一个很庞大的类,要详细叙述它的内

部工作机制,就要复制苹果的全部的优秀文档,这样会使这篇文章非常非常的Ӑ。所以,我建议你阅读NSView类的文档以获得这个类的细节认识,而这里我们

只谈怎么使用它。

我们不会直接和一个NSView的实例打交道,它是一个抽象类。我们要生成NSView的一个子类,并把我们的画图代码添加到这个子类中,并操作这个子类。PB

提供了创建NSView子类的框架的办法。

首先我们要做的是创建一个新的项目。把它称为:CocoaDrawing。在新项目打开以后,在文件菜单中选择“新建文件”。然后在新建文件对话框中选

择“Objective-C NSView subclass”作为你要创建的文件的类型。选择“然后”按钮,并把你新的文件命名为CocoaDrawing.m。确定已经选择同时创

建CocoaDrawing.h。选择“结束”按钮,你就有了一个NSView的类文件。

下一步是让你的程序知道我们的NSView的子类。这通过IB来完成。通过双击MainMenu.nib打开IB。保持IB打开,我们要耍一个小花招来把我们的新

类,CocoaDrawing,添加到IB已知的类中间去。我们把CocoaDrawing.h这个文件从PB的项目窗口中拖到IB的实例面板上。

这样就会把我们的新类,CocoaDrawing填加到如下图所示的类面板中。这种添加类到IB中的方法适用于你在PB中创建的任何类。事实上,这就是我们在IB

产生的代码中看到IBOutlet和IBAction这些标记的原因,它使得IB可以识别任何插座和动作。(译者:这里有一个小陷阱,在拖动之前需要保存你创建的

文件。但是,如果你没有对系统创建的文件进行过修改过的话,那么文件是不会真正保存的,拖动也就不成功了。所以,如果你暂时不知道要写些什么代码的

话,那么就改动一下注释里面的版本信息吧)。

下一步是拖一个CustomView容器到我们程序窗口中。在Cocoa容器(Containers)面板中,把一个定制视图(Custom View)对象拖到窗口上。

在CustomView被选中的情况下,打开Show Info面板,在属性下(应该是定制类,Custom Class下)你会在类列表中找到CocoaDrawing。选中它以后,

你会看到定制视图的标题变为CocoaDrawing。现在我们已经搞定了,下面要学习Cocoa的画笔了。在IB中保存你的改动,返回PB,并进入下一段。画笔

我们在Cocoa中的画笔是应用库中的NSBezierPath(贝塞尔路径)类。和NSView类似,NSBezierPath也是一个有许多精巧功能的类。很不幸的,我们

今天只能看到它表面的一小层,但我们以后会更深入的了解它

贝塞尔路径是用一系列直线和曲线来描述图形的对象。例如,一个Ӑ方形可以描述为四段直线。通过贝塞尔路径,你可以创建任意复杂的图形。在视图中绘制

一个图形的过程是首先创建一个路径,然后填充或者勾勒它。我们很快就会看到他们的例子。

我们写的所有绘图代码都通过drawRect:这个方法完成。对那些有Java二维绘图经验的人来说,drawRect:类似于paint()。这个方法的参数是要绘制的

矩形范围。

通常我们并不直接调用drawRect:。而是在视图中发生了一些改变需要重绘的时候,会告诉视图它需要被重绘。今天,我们并不需要告诉视图重绘它自己,

但在后面的章节我们需要这样做。

我们今天要做的只是简单地画一些Ӑ方形和椭圆,它们在代码上几乎是一样的。我们主要使用的两个方法是简便构造

器+bezierPathWithRect:和+bezierPathWithOvalInRect:。让我们先看看第一个例子是怎么回事。

在drawRect:这个方法中,我们加入下面的代码:

- (void)drawRect:(NSRect)rect

{

NSRect r = NSMakeRect(10, 10, 50, 60);

NSBezierPath *bp = [NSBezierPath bezierPathWithRect:r];

NSColor *color = [NSColor blueColor];

[color set];

[bp fill];

}

在第一行,我们定义了要成为贝塞尔路径的矩形范围。跟着,我们沿着矩形的周я建立一个贝塞尔路径对象。再下一行,我们创建一种将要用来填充矩形的色

彩,接下来,通过NSColor类的set方法设置当前和以后的绘图色彩。[color set]这个消息告诉后台图形引擎所有绘图操作的颜色是蓝色(由对象的颜色

指定)。最后,我们向贝塞尔路径对象发送一个填充指令,从而按照我们指定的颜色填充路径。这段代码应该可以产生下面的输出:

我们也可以把最后一行改为:[bp stroke],这样会沿着路径产生线条,就好象下面一样:现在,如果我们把产生贝塞尔路径的代码(第二行),改为:

NSBezierPath *bp = [NSBezierPath bexierPathWithOvalInRect:r];

这样屏幕上画出的图形将是一个在指定的矩形范围内的椭圆,就好象下图一样:

另外一种画矩形的办法是用基础函数NSRectFill,它以一个矩形结构变量作为参数。这个操作的颜色是当前图形环境的颜色。例如,我们可以把第一个例子

从使用NSBezierPath改为如下的代码:

- (void)drawRect:(NSRect)rect

{

NSRect r = NSMakeRect(10, 10, 50, 60);

NSColor *color = [NSColor blueColor];

[color set];

NSRectFill(r);

}

NSRectFill是绘制视图背景颜色的简便的办法。我们可以先设置背景色为当前颜色,然后把drawRect:的参数rect传递给NSRectFill。回到我们前面

的例子,我们可以用下面的办法把背景设为黑色:

- (void)drawRect:(NSRect)rect

{

NSRect r;

NSBezierPath *bp;

[[NSColor blackColor] set];

NSRectFill(rect);

r = NSMakeRect(10, 10, 50, 60);

bp = [NSBezierPath bezierPathWithRect:r];

[[NSColor blueColor] set];

[bp fill];

}

在这个例子中,我没有使用color这个变量,而是直接向[NSColor blueColor]返回的对象发送set消息。这段代码产生下面的输出:

这段给视图背景涂色的代码的原理是,当drawRect:被视图自动调用的时候,视图的я界将作为rect参数传递过来。另外一个需要注意的是,背景绘制的代

码必须在其他绘图代码之前。这是因为新绘制的对象是绘于原有的对象之上的。

结束语

我们已经介绍了Cocoa绘图类创建图形的主要形式,并不是很复杂。在下一章,我们将继续我们的图形和绘图的讨论,学习如何产生复杂的路径。在此之前,

享受一下你今天学到的内容,实验一下实现你自己的想法。我留给你一个可以在屏幕上随机生成矩形和椭圆的程序,就象下图一样。这是一个很简单的程序,

在绘图方面,没有使用我们今天的内容之外的知识。它可以在这里下载。下次见

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值