Go Back   iPod touch, iPhone, and iPad forum - Multi-Touch Fans > iPhone OS / iOS Ecosystem > iPhone OS Development > Development Tutorials

What are you waiting for? Join the hundreds of thousands of other iPod touch and iPhone users in our community. Talk about the latest apps and accessories, or post your question on the forums! All visitors must register before they can post and answer questions and participate in our lively community, so register for free today!
Reply
 
Thread Tools Search this Thread
  #1  
Old 01-16-2009
SkylarEC's Avatar
Super Moderator Emeritus
Join Date: Sep 2007
 
None
Default [Tutorial] Drawing to the screen.


Want to create a drawing app? Here you go. Clearly, you will need to make improvements to the drawing code, as I literally spent five minutes making this to test something for another app. Regardless, you should be able to get the gist of what's going on. What I am linking is just your basic standard xcode view based project. The only pertinent part of this are the touchsBegan, touchesMoved, and touchesEnded methods, which I will be posting in this thread.

To draw, simply draw. To move your finger over the screen. To create a dot, tap the screen. To clear the screen, double tap the screen. Simple.


Objective C Code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
   
    mouseSwiped = NO;
    UITouch *touch = [touches anyObject];
   
    if ([touch tapCount] == 2) {
        drawImage.image = nil;
        return;
    }

    lastPoint = [touch locationInView:self.view];
    lastPoint.y -= 20;

}


The first thing we do is set a bool to track whether or not we moved our finger across the screen. Since this is when we touch, we will set it (mouseSwiped) to NO. After getting our touch, we want to know whether the user double tapped. If they did, we set our canvas to an empty image and break out of the touchesBegan method. If we are still going through our code, that means that the user did not double tap. We will now set a CGPoint ivar we set to where we user tapped the screen. This is so we know from where the user moved their finger.


Objective C Code:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    mouseSwiped = YES;
   
    UITouch *touch = [touches anyObject];   
    CGPoint currentPoint = [touch locationInView:self.view];
    currentPoint.y -= 20;
   
   
    UIGraphicsBeginImageContext(self.view.frame.size);
    [drawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
    CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
    CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
    CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 0.0, 1.0);
    CGContextBeginPath(UIGraphicsGetCurrentContext());
    CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
    CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
    CGContextStrokePath(UIGraphicsGetCurrentContext());
    drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
   
    lastPoint = currentPoint;

}
;


First off, before we forget, let's set our mouseSwiped flag to YES, that way we can refer to it later. Next, let's get the location where the user moved their finger. We'll set that location to currentPoint.

Graphics Contexts are far beyond the average developer in this forum, so I won't get into them. Instead, and also because it would be overkill in this scenario, we will not be creating our own. Instead, we will be using a shortcut within UIKit called UIGraphicsGetCurrentContext() to gather the current context in which to work.

Begin the context with the size of our view in which we want to draw, and draw an image into it. We now want to set our line caps. This is what makes our lines not end in squares and look natural. There are other caps you can use, so feel free to experiment. Next, we're going to want to set the color with which we will be working. In this case, red.

Then, begin the actual drawing, we'll need to call CGContextBeginPath(...) and fill it in. First, we'll move to the point where we'd like to start. This is the point where the user tapped. Then, we'll call CGContextAddLineToPoint to add a line to the point we just set. The line extends from the first point you set to the point you set within AddLineToPoint function call. Finally, call CGContextStrokePath to stroke the path, ie color the line you just made.

And you have a line in your context, congrats. Let's create an image out of that and set it as our canvas. Make sure to end the context with which we ar eworking: UIGraphicsEndImageContext(); We want to reset the the touch down point as the point to where we just drew. This way, if the user keeps swiping, we can start from where we left off.

Lastly, and importantly, ignore that mouseMoved variable. In fact, delete it from your code. Seriously.


Objective C Code:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
   
    UITouch *touch = [touches anyObject];
   
    if ([touch tapCount] == 2) {
        drawImage.image = nil;
        return;
    }
   
   
    if(!mouseSwiped) {
        UIGraphicsBeginImageContext(self.view.frame.size);
        [drawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
        CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
        CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
        CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 0.0, 1.0);
        CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
        CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
        CGContextStrokePath(UIGraphicsGetCurrentContext());
        CGContextFlush(UIGraphicsGetCurrentContext());
        drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    }
}


In the touchesEnded method, the first thing we want to do is break out of the user double tapped. This is because the user has already cleared their canvas.

Now, if we are still in the function, then the user has not double tapped. Check to make see if the user has swiped. If they have, do nothing, we've already drawn, and there's no reason to do anything else.

Else, if the user did not swipe, we want to make a dot. Simply do exactly what we did in the touchesMoved. Only, instead of drawing a line, we draw a point.

Congrats, you now can draw within your application. Enjoy it.



Link: http://www.touchrepo.com/SampleCode/TEST_DRAW_APP.zip
__________________

Last edited by SkylarEC; 07-14-2009 at 03:15 PM..
  #2  
Old 01-16-2009
Steaps's Avatar
Multi-Touch Maniac
Join Date: Oct 2007
 
iPod touch 16GB
3.0 jailbroken
Your on a roll with these tutorials, i like it. Keep it up .
Maybe a UITableView Grouped tutorial next please? Like Settings.app UITableView kind of thing. Thanks .
  #3  
Old 01-16-2009
Nickll9009's Avatar
Multi-Touch Devotee
Join Date: Sep 2007
 
iPod touch 8GB
3.0 jailbroken
Quote:
Originally Posted by Stephen.4 View Post
Your on a roll with these tutorials, i like it. Keep it up .
Maybe a UITableView Grouped tutorial next please? Like Settings.app UITableView kind of thing. Thanks .
Are you using IB? Cause if you are, all you have to do is select the Table View, and go to attributes, and change it to grouped.
Sponsored Links
  #4  
Old 01-16-2009
Steaps's Avatar
Multi-Touch Maniac
Join Date: Oct 2007
 
iPod touch 16GB
3.0 jailbroken
Quote:
Originally Posted by Nickll9009 View Post
Are you using IB? Cause if you are, all you have to do is select the Table View, and go to attributes, and change it to grouped.
I know how to get it to grouped. I just have no clue what so ever on how to use and create one etc... I'm not good with anything really, just trying to learn.
  #5  
Old 01-16-2009
SkylarEC's Avatar
Super Moderator Emeritus
Join Date: Sep 2007
 
None
Keep this thread on topic.
  #6  
Old 01-18-2009
gojohnnyboi's Avatar
Multi-Touch Zealot
Join Date: Jan 2008
 
None 16GB
3.0
skylar, a question.

i understand everything but what this does:
Code:
CGContextFlush(UIGraphicsGetCurrentContext());
would you mind telling me what that does? =] thanks.
  #7  
Old 01-18-2009
SkylarEC's Avatar
Super Moderator Emeritus
Join Date: Sep 2007
 
None
What it does is forces the content of the window context to be flushed immediately. In this scenario, it does nothing (as it shouldn't do anything). The reason it is in the code was because this sample app was to prep for something else I was working on. Feel free to remove it from the code. Also, you probably don't want to really cal it, as the OS flushes automatically. I believe Apple recommends avoiding using this function call.
  #8  
Old 03-04-2009
Multi-Touch Amateur
Join Date: Mar 2009
 
Default except for one thing

This tutorial works great, thanks. Except for one thing that happens only when used on my iPhone device. When I draw with my finger, the paint doesn't appear until I lift or pause my finger. Then everything I did magically appears.

Any ideas?

QImageView.h:

#import <UIKit/UIKit.h>

@interface QImageView : UIImageView
{
BOOL mouseSwiped;
CGPoint lastPoint;
}

@end

QImageView.m:

#import "QImageView.h"


@implementation QImageView


- (id)initWithFrameCGRect)frame {
if (self = [super initWithFrame:frame]) {
// Initialization code
}
return self;
}


- (void)drawRectCGRect)rect {
// Drawing code
}


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

// Handles the start of a touch
- (void)touchesBeganNSSet *)touches withEventUIEvent *)event
{
mouseSwiped = NO;
UITouch *touch = [touches anyObject];

if ([touch tapCount] == 2)
{
self.image = nil;
return;
}

lastPoint = [touch locationInView:self];
//lastPoint.y -= 20;
}

// Handles the continuation of a touch.
- (void)touchesMovedNSSet *)touches withEventUIEvent *)event
{
mouseSwiped = YES;

UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self];
//currentPoint.y -= 20;

UIGraphicsBeginImageContext(self.frame.size);
[self.image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext( ), 5.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentCon text(), 1.0, 0.0, 0.0, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext() , lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContex t(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext()) ;
self.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

lastPoint = currentPoint;
}

// Handles the end of a touch event when the touch is a tap.
- (void)touchesEndedNSSet *)touches withEventUIEvent *)event
{
UITouch *touch = [touches anyObject];

if ([touch tapCount] == 2)
{
self.image = nil;
return;
}


if(!mouseSwiped) {
UIGraphicsBeginImageContext(self.frame.size);
[self.image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext( ), 5.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentCon text(), 1.0, 0.0, 0.0, 1.0);
CGContextMoveToPoint(UIGraphicsGetCurrentContext() , lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContex t(), lastPoint.x, lastPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext()) ;
CGContextFlush(UIGraphicsGetCurrentContext());
self.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
}

@end
  #9  
Old 03-04-2009
SkylarEC's Avatar
Super Moderator Emeritus
Join Date: Sep 2007
 
None
I can't do all the work for you ; )

It should be fairly simply for you to figure out a fix.
  #10  
Old 03-04-2009
Multi-Touch Amateur
Join Date: Mar 2009
 
You say that, but I've been trying to figure this out for 3 hours now.
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off


All times are GMT -7. The time now is 02:42 PM.

Recent blog posts: Recent threads:

Powered by vBulletin®
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Copyright 2007 - 2010 Vigorous Media LLC - All Rights Reserved.


no new posts
Page generated in 0.62352 seconds with 9 queries