【发布时间】:2020-02-11 01:12:48
【问题描述】:
[编辑:] 从我的项目的第一阶段继续前进:How do I re-define size/origin of app window in code, overriding nib/xib file parameters, with Obj-C, Xcode 11.3.1 on Mac OS X 10.15.2 (Catalina)?
我当前的目标非常简单(至少在抽象方面):我想(重新)为我空白的 Mac OS X 应用程序窗口中的像素着色。我想经济地做到这一点,尽可能少的代码行,因为查看大块代码真的很碍眼。
我真的不想处理图像和图像缓冲区或绘制最小的可见线和矩形,但我愿意尝试所有这些。最后,我阅读的 StackOverflow 和 Apple Kit 文章数不胜数。
最初的议程是:
1) 访问我的空白应用程序窗口的“内容”
2) 在该内容中指定我感兴趣的像素
3) 使用其颜色空间值访问该像素
4) 如果可能,直接重写值
看起来非常紧凑和简单,对吧?
这就是我的 AppDelegate 中发生的事情。我打开构造函数:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
/*
For a more complex app, it's probably better to not put a window into the Main Menu NIB.
Instead, make a separate NIB for the window.
Then, load it using a window controller object and ask that for its window.
*/
NSRect frame = [_window frame];
frame.origin.x = 0;
frame.origin.y = 0;
frame.size.width = 1425;
frame.size.height = 810;
[_window setFrame: frame display: YES];
接下来是我尝试绘制某种东西的尝试。
策略 #1 - NSRectFill:
NSRect pxl;
pxl.origin.x = 0;
pxl.origin.y = 0;
pxl.size.width = 128;
pxl.size.height = 128;
//_window.draw(_ dirtyRect: pxl)
NSRectFill(pxl);
//draw(_ dirtyRect: pxl);
策略 #2(我真的不想尝试这个,因为它让我觉得既便宜又懒惰) - NSBezierPath:
NSBezierPath * path = [NSBezierPath bezierPath];
[path setLineWidth: 4];
NSPoint startPoint = { 0, 0 };
NSPoint endPoint = { 128, 128 };
[path moveToPoint: startPoint];
[path lineToPoint: endPoint];
[[NSColor redColor] set];
[path stroke];
我知道我在这里画了一条线,但每一点都有帮助。
策略 #3 - 使用图像和图像代表对象:
NSImage * image;
//create and define a colorspace object:
NSColor * rgb = [NSColor colorWithDeviceRed:1.0f
green:1.0f
blue:1.0f
alpha:1.0f];
//load the defined colorspace data into image rep:
NSBitmapImageRep * imgRep = [[NSBitmapImageRep alloc] initWithData:[image TIFFRepresentation]];
[imgRep setColor:rgb atX:128.0 y:128.0];
当然,这个问题是图像对象不包含任何东西。那我在里面放什么?我必须在其中加载 XIB 文件吗?我在网上看到了一些解决方案,它们打败了“尽可能少写几行”的观点。
策略 #4 - 使用复杂而冗长的函数:
NSColor *MyColorAtScreenCoordinate(CGDirectDisplayID displayID, NSInteger x, NSInteger y)
{ //Function definition is not allowed here
CGImageRef image = CGDisplayCreateImageForRect(displayID, CGRectMake(x, y, 1, 1));
NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithCGImage:image];
CGImageRelease(image);
NSColor *color = [bitmap colorAtX:0 y:0];
[bitmap release];
}
然后它抱怨:
Function definition is not allowed here
所以我用- (void) 把它带到了全球范围内,但它还是抱怨:
Expected method body
策略 #5 - 使用 bitmapImageRepForCachingDisplayInRect()
NSData *data;
NSBitmapImageRep *rep;
rep = [self bitmapImageRepForCachingDisplayInRect:[self frame]];
[self cacheDisplayInRect:[self frame] toBitmapImageRep:rep];
data = [rep TIFFRepresentation];
它给了我:
No visible @interface for 'AppDelegate' declares the selector 'frame'
我不是刚刚定义了同一范围内的框架吗?
我用这个关闭我的委托构造函数:
[_window setFrame: frame display: YES];
}
在我尝试过的范围之外
策略 #6 - 自定义 drawRect():
- (void)drawRect:(NSRect)dirtyRect {
// set any NSColor for filling, say white:
[[NSColor whiteColor] setFill];
NSRectFill(dirtyRect);
[super drawRect:dirtyRect];
}
No visible @interface for 'NSObject' declares the selector 'drawRect:'
这是否意味着它不知道自己的 drawRect 函数?
策略 #7 - 从Mac OS Cocoa: Draw a simple pixel on a canvas 复制和粘贴一大块:
NSInteger width = 128;
NSInteger height = 128;
NSInteger dataLength = width * height * 4;
UInt8 *data = (UInt8*)malloc(dataLength * sizeof(UInt8));
//Fill pixel buffer with color data
for (int j=0; j<height; j++) {
for (int i=0; i<width; i++) {
//Here I'm just filling every pixel with red
float red = 1.0f;
float green = 0.0f;
float blue = 0.0f;
float alpha = 1.0f;
int index = 4*(i+j*width);
data[index] =255*red;
data[++index]=255*green;
data[++index]=255*blue;
data[++index]=255*alpha;
}
}
// Create a CGImage with the pixel data
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, data, dataLength, NULL);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGImageRef img = CGImageCreate(width, height, 8, 32, width * 4, colorspace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast,
provider, NULL, true, kCGRenderingIntentDefault);
//Clean up
CGColorSpaceRelease(colorspace);
CGDataProviderRelease(provider);
// Don't forget to free(data) when you are done with the CGImage
这些方法我都试过了;什么都没有。我在这里做错了吗?我的操作顺序错了吗?我试图让编译器和构建器保持所有语法兼容和可理解。
旁注1:我真的希望我可以使用尽可能少的类/对象来在空白窗口上放置一些东西。
旁注 2:我看过这么多 MVC 图,读过这么多文章,仍然不清楚什么是做什么的。我已经看到很多代码片段试图实现相同的目标,以至于很难相信有不止一种方法可以做一些基本的事情。
在窗口框架内为像素着色的简单行为已成为一个加载冒险,标记为过度利用缓冲区和 Xcode“无法识别”的对象。
No visible @interface declares this selector.
【问题讨论】:
标签: objective-c xcode macos cocoa graphics