Cocoa / Objective-C: Draw Rectangle on Button Click

Learn cocoa / objective-c: draw rectangle on button click with practical examples, diagrams, and best practices. Covers cocoa, button, drawing development techniques with visual explanations.

Drawing Rectangles on Button Click in Cocoa/Objective-C

Hero image for Cocoa / Objective-C: Draw Rectangle on Button Click

Learn how to dynamically draw a rectangle on a custom view in a Cocoa application using Objective-C, triggered by a button click.

In Cocoa applications, drawing custom shapes and graphics often involves overriding the drawRect: method of an NSView subclass. This article will guide you through the process of creating a simple macOS application where clicking a button triggers the drawing of a rectangle on a dedicated drawing area. We'll cover setting up the UI, creating a custom view, and implementing the drawing logic.

Setting Up the Project and UI

First, let's set up a new Cocoa application project in Xcode and design a basic user interface. We'll need a window, a button, and a custom view where our rectangle will be drawn. The custom view will be the canvas for our drawing operations.

1. Create a New Xcode Project

Open Xcode and create a new project. Choose 'macOS' -> 'App' and select 'Cocoa App' as the template. Name your project (e.g., 'RectangleDrawer') and ensure 'Language' is set to 'Objective-C'.

2. Design the User Interface

Open MainMenu.xib (or Main.storyboard if you're using storyboards). Drag a Push Button and a Custom View from the Object Library onto your main window. Resize the custom view to be a prominent drawing area. Connect the button's IBAction to your AppDelegate or a new ViewController.

3. Create a Custom NSView Subclass

Create a new Objective-C class, subclassing NSView. Name it DrawingView. This will be our custom drawing canvas. In MainMenu.xib, select your Custom View and change its class in the Identity Inspector to DrawingView.

flowchart TD
    A[Start Xcode Project] --> B{Choose Cocoa App Template}
    B --> C[Design UI in MainMenu.xib]
    C --> D[Add Push Button]
    C --> E[Add Custom View]
    E --> F[Set Custom View Class to DrawingView]
    D --> G[Connect Button Action]
    F --> H[Implement Drawing Logic in DrawingView]
    G --> I[Trigger Redraw on Button Click]
    H --> J[End]

Project Setup Workflow for Drawing a Rectangle

Implementing the Drawing Logic in DrawingView

The core of our drawing functionality will reside in the DrawingView class. We'll override its drawRect: method to perform the actual drawing. To make the drawing dynamic, we'll introduce a property to control whether the rectangle should be drawn.

// DrawingView.h
#import <Cocoa/Cocoa.h>

NS_ASSUME_NONNULL_BEGIN

@interface DrawingView : NSView

@property (nonatomic, assign) BOOL shouldDrawRectangle;

@end

NS_ASSUME_NONNULL_END
// DrawingView.m
#import "DrawingView.h"

@implementation DrawingView

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];
    
    // Drawing code here.
    if (self.shouldDrawRectangle) {
        NSRect rectToDraw = NSMakeRect(50, 50, 100, 80);
        [[NSColor blueColor] setFill];
        NSRectFill(rectToDraw);
        
        [[NSColor redColor] setStroke];
        NSBezierPath *path = [NSBezierPath bezierPathWithRect:rectToDraw];
        [path setLineWidth:3.0];
        [path stroke];
    }
}

// When shouldDrawRectangle changes, we need to tell the view to redraw
- (void)setShouldDrawRectangle:(BOOL)shouldDrawRectangle {
    _shouldDrawRectangle = shouldDrawRectangle;
    [self setNeedsDisplay:YES]; // Mark the view as needing redrawing
}

@end

Connecting the Button to the Drawing View

Finally, we need to connect our button's action to update the shouldDrawRectangle property of our DrawingView instance. This will cause the view to redraw itself and display the rectangle.

1. Create an IBOutlet for DrawingView

In your AppDelegate.h (or ViewController.h), create an IBOutlet for your DrawingView. For example: @property (nonatomic, weak) IBOutlet DrawingView *drawingCanvas;.

2. Connect IBOutlet in Interface Builder

Go back to MainMenu.xib. Control-drag from your AppDelegate (or ViewController) to the DrawingView and connect it to the drawingCanvas outlet.

3. Implement the Button Action

In your AppDelegate.m (or ViewController.m), implement the IBAction method connected to your button. Inside this method, toggle the shouldDrawRectangle property of your drawingCanvas.

// AppDelegate.h (or ViewController.h)
#import <Cocoa/Cocoa.h>
#import "DrawingView.h"

@interface AppDelegate : NSObject <NSApplicationDelegate>

@property (nonatomic, weak) IBOutlet DrawingView *drawingCanvas;

- (IBAction)drawRectangleButtonClicked:(id)sender;

@end
// AppDelegate.m (or ViewController.m)
#import "AppDelegate.h"

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // Insert code here to initialize your application
}

- (void)applicationWillTerminate:(NSNotification *)aNotification {
    // Insert code here to tear down your application
}

- (IBAction)drawRectangleButtonClicked:(id)sender {
    // Toggle the drawing state
    self.drawingCanvas.shouldDrawRectangle = !self.drawingCanvas.shouldDrawRectangle;
    NSLog(@"Button clicked! Rectangle drawing state: %d", self.drawingCanvas.shouldDrawRectangle);
}

@end

Now, when you run the application and click the button, the drawRectangleButtonClicked: method will be invoked. This method toggles the shouldDrawRectangle property of your DrawingView. Because setShouldDrawRectangle: calls setNeedsDisplay:YES, the DrawingView will be marked for redrawing, and its drawRect: method will be called, either drawing or clearing the rectangle based on the property's state.