I'm trying to follow Quartz 2D programming guide using RubyMotion.
Here's my AppDelegate
:
class AppDelegate
def applicationDidFinishLaunching(notification)
buildMenu
buildWindow
end
def buildWindow
@window = NSWindow.alloc.initWithContentRect([[240, 180], [480, 360]],
styleMask: NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask,
backing: NSBackingStoreBuffered,
defer: false)
@window.title = NSBundle.mainBundle.infoDictionary['CFBundleName']
@window.orderFrontRegardless
@view = MyQuartzView.alloc.initWithFrame(@window.frame)
@window.contentView.addSubview @view
end
end
And here is my MyQuartzView
, which is supposed to be direct translation from code in the guide:
class MyQuartzView < NSView
def drawRect(rect)
myContext = NSGraphicsContext.currentContext.graphicsPort
CGContextSetRGBFillColor(myContext, 1, 0, 0, 1)
CGContextFillRect(myContext, CGRectMake(0, 0, 200, 100))
CGContextSetRGBFillColor(myContext, 0, 0, 1, 0.5)
CGContextFillRect(myContext, CGRectMake(0, 0, 100, 200))
end
end
I'm getting the following errors:
<Error>: CGContextSetRGBFillColor: invalid context 0x10222bad0
<Error>: CGContextFillRects: invalid context 0x10222bad0
<Error>: CGContextSetRGBFillColor: invalid context 0x10222bad0
<Error>: CGContextFillRects: invalid context 0x10222bad0
Why is the context invalid? I'm inside drawRect
method.
EDIT
If I change window rect to [[340, 380], [480, 360]]
the error goes away, but drawRect
is not called. However, when I resize window, it gets called with same errors.
EDIT 2 This is an OS X app.
EDIT 3 Interesting, the same program in Objective-C works fine:
// main.m
#import <Cocoa/Cocoa.h>
#import "MyQuartzView.h"
int main(int argc, const char * argv[])
{
NSApplication *app = [NSApplication sharedApplication];
NSRect frame = NSMakeRect(100., 100., 300., 300.);
NSWindow *window = [[NSWindow alloc]
initWithContentRect: frame
styleMask: NSTitledWindowMask | NSClosableWindowMask
backing: NSBackingStoreBuffered
defer: false];
[window setTitle: @"Test"];
id view = [[MyQuartzView alloc] initWithFrame: frame];
[window setContentView: view];
[window setDelegate: view];
[window orderFrontRegardless];
[app run];
return EXIT_SUCCESS;
}
// MyQuartzView.m
#import "MyQuartzView.h"
@implementation MyQuartzView
- (id)initWithFrame:(NSRect)frame
{
return[super initWithFrame:frame];
}
- (void)drawRect:(NSRect)dirtyRect
{
CGContextRef myContext = [[NSGraphicsContext currentContext] graphicsPort];
CGContextSetRGBFillColor (myContext, 1, 0, 0, 1);
CGContextFillRect (myContext, CGRectMake (0, 0, 200, 100));
CGContextSetRGBFillColor (myContext, 0, 0, 1, .5);
CGContextFillRect (myContext, CGRectMake (0, 0, 100, 200));
}
@end
Here's the magic to make it work: You need to call to_object
when you get the context:
myContext = NSGraphicsContext.currentContext.graphicsPort.to_object
I implemented your code in a RubyMotion project, and this was the result: