gpt4 book ai didi

objective-c - Cocoa:删除自定义 NSView 的一部分并显示下面的内容?

转载 作者:行者123 更新时间:2023-12-03 16:48:35 25 4
gpt4 key购买 nike

Problem description

[[NSColor clearColor] set];
NSRectFillUsingOperation(win, NSCompositeCopy);

"copy" result

我也尝试过 NSCompositeClear、NSCompositeDestinationOut,但它们都没有按照我的意愿工作。我想删除蓝色剪辑窗口中的背景,这样它的内容就会更亮。我只学习了 Cocoa 和 obj-c 一周,所以也许我误解了一些东西。我很想知道如何在Cocoa框架中实现这一点?

#import "ImageCutterView.h"
#define CONTROL_POINT_SIZE 6
#define CLIP_WINDOW_MIN_SIZE 100
#define CLIP_WINDOW_MAX_SIZE 200

@implementation ImageCutterView {
NSRect win;
NSRect controlPoints[4];
CGFloat gridLinePattern[2];
NSBezierPath* gridLines[4];
NSPoint p1,p2;

BOOL startDragging;
BOOL topLeftDragging;
BOOL topRightDragging;
BOOL bottomLeftDragging;
BOOL bottomRightDragging;

NSColor *borderColor;
NSColor *gridColor;
NSColor *controlPointBorderColor;
NSColor *controlPointFillColor;
NSColor *backgroundColor;

CGFloat distance, preDistance;

NSCursor *diagonal1, *diagonal2;
}

-(void)calculateControlPolints{
CGFloat w, h;
w = win.size.width;
h = win.size.height;
CGFloat ox,oy;
ox = win.origin.x;
oy = win.origin.y;
controlPoints[0].origin.x = ox - CONTROL_POINT_SIZE/2;
controlPoints[0].origin.y = oy - CONTROL_POINT_SIZE/2;
controlPoints[0].size.width = CONTROL_POINT_SIZE;
controlPoints[0].size.height = CONTROL_POINT_SIZE;
controlPoints[1].origin.x = ox - CONTROL_POINT_SIZE/2;
controlPoints[1].origin.y = oy + h - CONTROL_POINT_SIZE/2;
controlPoints[1].size.width = CONTROL_POINT_SIZE;
controlPoints[1].size.height = CONTROL_POINT_SIZE;
controlPoints[2].origin.x = ox + w - CONTROL_POINT_SIZE/2;
controlPoints[2].origin.y = oy + h - CONTROL_POINT_SIZE/2;
controlPoints[2].size.width = CONTROL_POINT_SIZE;
controlPoints[2].size.height = CONTROL_POINT_SIZE;
controlPoints[3].origin.x = ox + w - CONTROL_POINT_SIZE/2;
controlPoints[3].origin.y = oy - CONTROL_POINT_SIZE/2;
controlPoints[3].size.width = CONTROL_POINT_SIZE;
controlPoints[3].size.height = CONTROL_POINT_SIZE;
}
-(void)calculateGridLines{
CGFloat w, h, w3, h3;
w = win.size.width;
h = win.size.height;
w3 = w/3;
h3 = h/3;
CGFloat ox,oy;
ox = win.origin.x;
oy = win.origin.y;
gridLines[0] = [NSBezierPath bezierPath];
[gridLines[0] setLineDash:gridLinePattern count:2 phase:0.0];
[gridLines[0] moveToPoint:NSMakePoint(ox + w3, oy + h)];
[gridLines[0] lineToPoint:NSMakePoint(ox + w3, oy)];
gridLines[1] = [NSBezierPath bezierPath];
[gridLines[1] setLineDash:gridLinePattern count:2 phase:0.0];
[gridLines[1] moveToPoint:NSMakePoint(ox + w3*2, oy + h)];
[gridLines[1] lineToPoint:NSMakePoint(ox + w3*2, oy)];
gridLines[2] = [NSBezierPath bezierPath];
[gridLines[2] setLineDash:gridLinePattern count:2 phase:0.0];
[gridLines[2] moveToPoint:NSMakePoint(ox, oy + h3*2)];
[gridLines[2] lineToPoint:NSMakePoint(ox + w, oy + h3*2)];
gridLines[3] = [NSBezierPath bezierPath];
[gridLines[3] setLineDash:gridLinePattern count:2 phase:0.0];
[gridLines[3] moveToPoint:NSMakePoint(ox, oy + h3)];
[gridLines[3] lineToPoint:NSMakePoint(ox +w, oy + h3)];
}

-(NSCursor *)getSystemCursorByName:(NSString *)cursorName {
NSString *cursorPath = [@"/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/Resources/cursors" stringByAppendingPathComponent:cursorName];
NSImage *image = [[NSImage alloc] initByReferencingFile:[cursorPath stringByAppendingPathComponent:@"cursor.pdf"]];
NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[cursorPath stringByAppendingPathComponent:@"info.plist"]];
NSCursor *cursor = [[NSCursor alloc] initWithImage:image hotSpot:NSMakePoint([[info valueForKey:@"hotx"] doubleValue], [[info valueForKey:@"hoty"] doubleValue])];
return cursor;
}

-(void)awakeFromNib {
_showGrid = YES;
CGFloat cx,cy;
cx = self.frame.size.width / 2;
cy = self.frame.size.height / 2;
win.size.width = (CLIP_WINDOW_MIN_SIZE + CLIP_WINDOW_MAX_SIZE) / 2;
win.size.height = (CLIP_WINDOW_MIN_SIZE + CLIP_WINDOW_MAX_SIZE) / 2;
win.origin = NSMakePoint(cx - win.size.width/2, cy - win.size.height/2);

gridLinePattern[0] = 6.0;
gridLinePattern[1] = 4.0;

startDragging = NO;
topLeftDragging = NO;
topRightDragging = NO;
bottomLeftDragging = NO;
bottomRightDragging = NO;

borderColor = [NSColor colorWithSRGBRed:(0x44 + 1.0)/256 green:(0xce + 1.0)/256 blue:(0xf6 + 1.0)/256 alpha:0.8f];
gridColor = [NSColor colorWithSRGBRed:(0x44 + 1.0)/256 green:(0xce + 1.0)/256 blue:(0xf6 + 1.0)/256 alpha:0.8f];
controlPointBorderColor = [NSColor colorWithSRGBRed:(0x44 + 1.0)/256 green:(0xce + 1.0)/256 blue:(0xf6 + 1.0)/256 alpha:0.8f];
controlPointFillColor = [NSColor whiteColor];
backgroundColor = [NSColor colorWithSRGBRed:0.7 green:0.7 blue:0.7 alpha:0.4f];
//backgroundColor = [NSColor blackColor];

[self calculateControlPolints];
[self calculateGridLines];

diagonal1 = [self getSystemCursorByName:@"resizenorthwestsoutheast"];
diagonal2 = [self getSystemCursorByName:@"resizenortheastsouthwest"];

};

//-(BOOL)isOpaque{
// return YES;
//}

- (void)resetCursorRects
{
[super resetCursorRects];
if (diagonal1) {
[self addCursorRect:controlPoints[1] cursor: diagonal1];
[self addCursorRect:controlPoints[3] cursor: diagonal1];
}
if(diagonal2){
[self addCursorRect:controlPoints[0] cursor: diagonal2];
[self addCursorRect:controlPoints[2] cursor: diagonal2];
}
}

- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
NSGraphicsContext* ctx = [NSGraphicsContext currentContext];
[ctx setShouldAntialias:NO];
[NSBezierPath setDefaultLineWidth:0.0];
[backgroundColor set];
[NSBezierPath fillRect:dirtyRect];

/*
[ctx saveGraphicsState];
//[ctx setCompositingOperation:NSCompositeDestinationOut];
//[ctx setCompositingOperation:NSCompositeDestinationOver];
[ctx setCompositingOperation:NSCompositeCopy];
[[NSColor clearColor] set];
[NSBezierPath fillRect:win];
[ctx restoreGraphicsState];*/

[[NSColor clearColor] set];
//[[NSColor colorWithSRGBRed:1.0f green:1.0f blue:1.0f alpha:0.0f] set];
NSRectFillUsingOperation(win, NSCompositeCopy);

[[NSColor colorWithSRGBRed:(0x44 + 1.0)/256 green:(0xce + 1.0)/256 blue:(0xf6 + 1.0)/256 alpha:0.8f] set];
[NSBezierPath strokeRect:win];
if (self.showGrid) {
for (int i=0; i<4; i++) {
[gridLines[i] stroke];
}
}
[[NSColor colorWithSRGBRed:(0x44 + 1.0)/256 green:(0xce + 1.0)/256 blue:(0xf6 + 1.0)/256 alpha:1.0f] set];
for (int i=0; i<4; i++) {
[NSBezierPath strokeRect:controlPoints[i]];
}
}

-(void)mouseDown:(NSEvent *)theEvent {
p1 = [theEvent locationInWindow];
NSPoint tp = [self convertPoint:p1 fromView:nil];
if (NSPointInRect(tp, controlPoints[0])){
bottomLeftDragging = YES;
} else if (NSPointInRect(tp, controlPoints[1])){
topLeftDragging = YES;
p1 = NSMakePoint(win.origin.x, win.origin.y + win.size.height);
preDistance = ((tp.x-p1.x) - (tp.y - p1.y)) / 2;
} else if (NSPointInRect(tp, controlPoints[2])){
topRightDragging = YES;
} else if (NSPointInRect(tp, controlPoints[3])){
bottomRightDragging = YES;
} else if (NSPointInRect(tp, win)) {
startDragging = YES;
}
}

-(void)mouseDragged:(NSEvent *)theEvent {
p2 = [theEvent locationInWindow];
if (startDragging) {
NSAffineTransform *transfrom = [NSAffineTransform transform];
[transfrom translateXBy:p2.x - p1.x yBy:p2.y - p1.y];
win.origin = [transfrom transformPoint:win.origin];
for(int i=0;i<4;i++){
controlPoints[i].origin = [transfrom transformPoint:controlPoints[i].origin];
}
for (int i=0; i<4; i++) {
[gridLines[i] transformUsingAffineTransform:transfrom];
}
[self setNeedsDisplay:YES];
p1 = p2;
} else if (topLeftDragging) {
p2 = [self convertPoint:p2 fromView:nil];
distance = ((p2.x-p1.x) - (p2.y - p1.y)) / 2;
CGFloat dSize = distance - preDistance;
CGFloat newSize = win.size.width - dSize;
if (newSize >= CLIP_WINDOW_MIN_SIZE && newSize <= CLIP_WINDOW_MAX_SIZE){
preDistance = distance;
win.size.width = newSize;
win.size.height = newSize;
win.origin.x += dSize;
[self calculateControlPolints];
[self calculateGridLines];
[self setNeedsDisplay:YES];
}
} else if (topRightDragging) {
} else if (bottomLeftDragging) {
} else if (bottomRightDragging) {
}
}

- (void)mouseUp:(NSEvent *)theEvent {
if (startDragging){
startDragging = NO;
} else if (topLeftDragging){
topLeftDragging = NO;
} else if (topRightDragging){
topRightDragging = NO;
} else if (bottomLeftDragging) {
bottomLeftDragging = NO;
} else if (bottomRightDragging) {
bottomRightDragging = NO;
}
[self resetCursorRects];
}
@end

我发现了一个和我13年前问过的问题一样的问题。 http://www.cocoabuilder.com/archive/cocoa/47367-clearing-an-nsview.html

[更新 1]我总是想知道为什么 NSCompositeClear 没有正确清除我的源区域(不要向我显示黑洞)。所以我想到了一个想法,奇怪的事情发生是因为我画到了屏幕上。如果我绘制位图图像的 NSGraphicsContext 会怎样?

@implementation FooView {
NSBitmapImageRep *offscreenRep;
NSRect imgRect;
NSSize imgSize;
}
-(void)awakeFromNib{
imgRect = NSMakeRect(0.0, 0.0, 100.0, 100.0);
imgSize = imgRect.size;

offscreenRep = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes:NULL
pixelsWide:imgSize.width
pixelsHigh:imgSize.height
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSDeviceRGBColorSpace
bitmapFormat:NSAlphaFirstBitmapFormat
bytesPerRow:0
bitsPerPixel:0];
}
- (void)drawRect:(NSRect)dirtyRect {
// set offscreen context
NSGraphicsContext *g = [NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:g];

//draw something here
NSBezierPath *circle = [NSBezierPath bezierPathWithOvalInRect:NSMakeRect(20, 20, 50, 50)];
NSBezierPath *rectangle = [NSBezierPath bezierPathWithRect:NSMakeRect(5, 5, 40, 40)];
[[NSColor greenColor] set];
[circle fill];
[g setCompositingOperation:NSCompositeClear];
[[NSColor redColor] set];
[rectangle fill];

// done drawing, so set the current context back to what it was
[NSGraphicsContext restoreGraphicsState];

// create an NSImage and add the rep to it
NSImage *img = [[NSImage alloc] initWithSize:imgSize];
[img addRepresentation:offscreenRep];

// then go on to save or view the NSImage
[img drawAtPoint:NSMakePoint(0.0, 0.0)
fromRect: NSMakeRect(0.0, 0.0, 100.0, 100.0)
operation: NSCompositeSourceOver
fraction: 1.0];
}
...

我从(Mac OS X: Drawing into an offscreen NSGraphicsContext using CGContextRef C functions has no effect. Why?)复制了绘图代码并做了一些更改。有效!所以证明了我上面的假设。不过,现在有 2 个新问题。

  1. 为什么绘制到屏幕上和绘制到图像上有不同?
  2. 上面绘制图像的代码效率不高。当我移动窗口时内容会闪烁。

[更新2]问题1:也许没有区别。 “layer 0”:黑色,“layer 1”:窗口内容,“layer 2”:我的图像层。当我绘制到屏幕上时,我实际上是在第 1 层上绘制。当我绘制到图像上时,我实际上是在我的自定义“层”2 上绘制。

最佳答案

首先,感谢您写出如此经过深思熟虑的问题并对这个主题进行了如此多的研究!

我也遇到了同样的问题。而且,我也很困惑为什么你尝试的混合模式不起作用。我开始相信问题出在我(和你)的心理模型上,即 NSView 的 drawRect 操作期间到底发生了什么。这无论如何都不是确定的,只是我对正在发生的事情的解释。

对于图像,现在有两个“像素缓冲区”,即图像和 NSView 占据的屏幕内容。混合模式在这些情况下有效,因为同时存在源和目标。当您只是在drawRect中绘制/填充时,任何绘制操作都必然会覆盖屏幕上的像素。因此,您无法通过使用不同的复合操作来撤消像素更改。 dest 始终是屏幕的当前状态,而不是为 View 绘图创建的临时像素缓冲区。再说一遍,不是专家。

有关可能适合您的解决方案,请查看 https://stackoverflow.com/a/32200161/288405 .

关于objective-c - Cocoa:删除自定义 NSView 的一部分并显示下面的内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27253107/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com