在 iPhone 上使用 Quartz 2D 进行基本绘图

发布于 2024-08-31 03:03:07 字数 1934 浏览 0 评论 0原文

我的目标是制作一个程序,每当触摸屏幕时都会绘制点。这是我到目前为止所拥有的:

头文件:

#import <UIKit/UIKit.h>


@interface ElSimView : UIView 
{
  CGPoint firstTouch;
  CGPoint lastTouch;
  UIColor *pointColor;
  CGRect *points;
  int npoints;
}

@property CGPoint firstTouch;
@property CGPoint lastTouch;
@property (nonatomic, retain) UIColor *pointColor;
@property CGRect *points;
@property int npoints;

@end

实现文件:

//@synths etc.

- (id)initWithFrame:(CGRect)frame 
{
    return self;
}


- (id)initWithCoder:(NSCoder *)coder
{
  if(self = [super initWithCoder:coder])
  {
    self.npoints = 0;
  }
  return self;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
  UITouch *touch = [touches anyObject];
  firstTouch = [touch locationInView:self];
  lastTouch = [touch locationInView:self];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
  UITouch *touch = [touches anyObject];
  lastTouch = [touch locationInView:self];  
  points = (CGRect *)malloc(sizeof(CGRect) * ++npoints);
  points[npoints-1] = CGRectMake(lastTouch.x-15, lastTouch.y-15,30,30);
  [self setNeedsDisplay];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
  UITouch *touch = [touches anyObject];
  lastTouch = [touch locationInView:self];  
  [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect 
{
  CGContextRef context = UIGraphicsGetCurrentContext();

  CGContextSetLineWidth(context, 2.0);
  CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);
  CGContextSetFillColorWithColor(context, pointColor.CGColor);

  for(int i=0; i<npoints; i++)
    CGContextAddEllipseInRect(context, points[i]);
  CGContextDrawPath(context, kCGPathFillStroke);
}


- (void)dealloc {
    free(points);
    [super dealloc];
}


@end

当我加载它并单击某些点时,它会正常绘制第一个点,然后接下来的点与随机椭圆(甚至不是圆形)一起绘制。

另外我还有一个问题:确切drawRect什么时候执行?

My goal is to make a program that will draw points whenever the screen is touched. This is what I have so far:

The header file:

#import <UIKit/UIKit.h>


@interface ElSimView : UIView 
{
  CGPoint firstTouch;
  CGPoint lastTouch;
  UIColor *pointColor;
  CGRect *points;
  int npoints;
}

@property CGPoint firstTouch;
@property CGPoint lastTouch;
@property (nonatomic, retain) UIColor *pointColor;
@property CGRect *points;
@property int npoints;

@end

The implementation file:

//@synths etc.

- (id)initWithFrame:(CGRect)frame 
{
    return self;
}


- (id)initWithCoder:(NSCoder *)coder
{
  if(self = [super initWithCoder:coder])
  {
    self.npoints = 0;
  }
  return self;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
  UITouch *touch = [touches anyObject];
  firstTouch = [touch locationInView:self];
  lastTouch = [touch locationInView:self];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
  UITouch *touch = [touches anyObject];
  lastTouch = [touch locationInView:self];  
  points = (CGRect *)malloc(sizeof(CGRect) * ++npoints);
  points[npoints-1] = CGRectMake(lastTouch.x-15, lastTouch.y-15,30,30);
  [self setNeedsDisplay];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
  UITouch *touch = [touches anyObject];
  lastTouch = [touch locationInView:self];  
  [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect 
{
  CGContextRef context = UIGraphicsGetCurrentContext();

  CGContextSetLineWidth(context, 2.0);
  CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);
  CGContextSetFillColorWithColor(context, pointColor.CGColor);

  for(int i=0; i<npoints; i++)
    CGContextAddEllipseInRect(context, points[i]);
  CGContextDrawPath(context, kCGPathFillStroke);
}


- (void)dealloc {
    free(points);
    [super dealloc];
}


@end

When I load this and click some points, it draws the first points normally, then then next points are drawn along with random ellipses (not even circles).

Also I have another question: When is exactly drawRect executed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

ゞ记忆︶ㄣ 2024-09-07 03:03:07

在 -touchesEnded:withEvent: 中,您有以下代码:

points = (CGRect *)malloc(sizeof(CGRect) * ++npoints);
points[npoints-1] = CGRectMake(lastTouch.x-15, lastTouch.y-15,30,30);

您正在为 points 重新分配一个数组,但不会复制之前的任何点。这导致您使用随机的未初始化内存值而不是保存的 CGRect。相反,请尝试如下操作:

CGRect *newPoints = (CGRect *)malloc(sizeof(CGRect) * ++npoints);
for (unsigned int currentPoint = 0; currentPoint < (npoints - 1); currentPoint++)
{
    newPoints[currentPoint] = points[currentPoint];
}
free(points);
points = newPoints;

points[npoints-1] = CGRectMake(lastTouch.x-15, lastTouch.y-15,30,30);

之前您还通过在为其内容分配新数组之前未释放它而泄漏了 points 数组。

至于-drawRect:被调用的时候,它是在iPhone OS显示系统需要重新缓存UIView的内容时触发的。正如 Daniel 所说,这种情况通常会在初始显示时以及您在 UIView 上手动调用 -setNeedsDisplay 时发生一次。

In -touchesEnded:withEvent:, you have the following code:

points = (CGRect *)malloc(sizeof(CGRect) * ++npoints);
points[npoints-1] = CGRectMake(lastTouch.x-15, lastTouch.y-15,30,30);

You are re-allocating an array for points, but not copying over any of your previous points. This was causing you to use random uninitialized memory values instead of your saved CGRects. Instead, try something like the following:

CGRect *newPoints = (CGRect *)malloc(sizeof(CGRect) * ++npoints);
for (unsigned int currentPoint = 0; currentPoint < (npoints - 1); currentPoint++)
{
    newPoints[currentPoint] = points[currentPoint];
}
free(points);
points = newPoints;

points[npoints-1] = CGRectMake(lastTouch.x-15, lastTouch.y-15,30,30);

You were also leaking the points array before by not freeing it before allocating a new array for its contents.

As far as when -drawRect: is called, it is triggered when the iPhone OS display system needs to recache the content of a UIView. As Daniel stated, this typically happens once on initial display and whenever you manually call -setNeedsDisplay on the UIView.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文