gpt4 book ai didi

objective-c - 在 Cocoa 中绘图,xy 值错误

转载 作者:行者123 更新时间:2023-12-03 17:16:52 24 4
gpt4 key购买 nike

我试图在 NSScrollView 内的 NSView 中绘制一堆矩形。代码运行得很好,但计算机似乎在错误的点上绘制。

当我使用 NSLog() 记录当前的 xy 时,值是正确的,但是当我查看我的 View 时,在绘图坐标之前添加了额外的空格。

这是代码:

//
// CoverFlowView.m
// iWatch
//
// Created by ief2 on 03/11/10.
//
//

#import "CoverFlowView.h"

#pragma mark Defaults
#define COVER_HEIGHT2WIDTH(a) ((float)a / 1.4)
#define COVER_HEIGHT (200.0)
#define COVER_WIDTH (COVER_HEIGHT2WIDTH(COVER_HEIGHT))
#define COVER_SPACE_MIN (20.0)

#pragma mark Private Methods
@interface CoverFlowView (PrivateMethods)
- (CGFloat)coverSpaceForMoviesPerLine:(NSUInteger *)n;
- (void)frameDidChange;
- (void)updateFrame;
@end

NSColor *RandomColor() {
float red = (float)(rand() % 255) / 254.0;
float green = (float)(rand() % 255) / 254.0;
float blue = (float)(rand() % 255) / 254.0;

NSColor *theColor = [[NSColor colorWithDeviceRed:red
green:green
blue:blue
alpha:1.0] retain];
return [theColor autorelease];
}

#pragma mark Implementation
@implementation CoverFlowView
#pragma mark Init and Dealloc
- (void)awakeFromNib {
srand(time(NULL));
NSMutableArray *colors = [[NSMutableArray alloc] initWithCapacity:100];
register int i;
for(i = 0; i < 100; i++) {
[colors addObject:RandomColor()];
}
self.movies = colors;
[colors autorelease];

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(frameDidChange)
name:NSViewFrameDidChangeNotification
object:self];

}

- (id)initWithFrame:(NSRect)frame movies:(NSArray *)movs {

self = [super initWithFrame:frame];
if(self != nil) {
self.movies = movs;

// FIXME: Debug color array to movie
NSMutableArray *colors = [[NSMutableArray alloc] initWithCapacity:100];
register int i;
srand((unsigned int)time(NULL));
for(i = 0; i < 100; i++) {
[colors addObject:RandomColor()];
}
}
return self;
}

- (void)dealloc {
[_movies release];

[super dealloc];
}

#pragma mark Drawing
- (void)drawRect:(NSRect)dirtyRect {
[[NSColor blackColor] setFill];
NSRectFill(dirtyRect);

NSUInteger moviesPerLine = 0;
CGFloat coverSpace = 0;

// Get the values
coverSpace = [self coverSpaceForMoviesPerLine:&moviesPerLine];



// if it's less than 1, break the drawing
if(moviesPerLine < 1) {
return;
}

// get the rows not to draw
// p = top left point's y
// h = movie cover height ->\
// s = space between -->The movies height and it's space above it
//
// p
// f(x) = -------
// h + s
double rows = ((dirtyRect.origin.y) / (COVER_HEIGHT + coverSpace));


// get the first movie that has to be drawn
// could be half-draw
//
// (NSUInteger)rows * moviesPerLine
NSUInteger index = (NSUInteger)rows * moviesPerLine;
if(!(index < [self.movies count]))
return;


// variable declaration
CGFloat curY;
CGFloat curX;

// start drawing until the line after max
// start the loop
do {
NSUInteger rowIndex;
// get the y for the movie
// x = movie index (start from 1)
// m = movies per row
// h = movie height
// s = movie space
//
// [x - (x % m)]
// f(x) = (|-----------|) * (h + s) + s
// [ m ]
// BUT: if rows == 2, rows -= 1
rowIndex = ((index + 1) - ((index + 1) % moviesPerLine)) / moviesPerLine;
((index + 1) % moviesPerLine == 0) ? (rowIndex -= 1) : (rowIndex = rowIndex);
curY = rowIndex * (COVER_HEIGHT + coverSpace) + coverSpace;


// get the x fot the movie
// x = movie index (start from 1)
// m = movies per line
// w = movie width
// s = cover space
//
//
// f(x) = ((x - (x - (x % m))) - 1) * (w + s) + s
// BUT: if row == 0, row = m
//
rowIndex = (index+1) - (((index+1) - ((index + 1) % moviesPerLine)));
(rowIndex == 0) ? (rowIndex = moviesPerLine) : (rowIndex = rowIndex);
curX = (rowIndex - 1) * (COVER_WIDTH + coverSpace) + coverSpace;
NSLog(@"%s index: %3u || x: %5.0f || y: %5.0f", __FUNCTION__, index, curX, curY);

// Start the drawing
NSRect bezierPathRect = NSMakeRect(curX + coverSpace, curY, COVER_WIDTH, COVER_HEIGHT);
NSBezierPath *path = [NSBezierPath bezierPathWithRect:bezierPathRect];
[path setLineWidth:2.0];
[[NSColor whiteColor] setStroke];
[(NSColor *)[self.movies objectAtIndex:index] setFill];
[path fill];
[path stroke];

// add up values
index++;
if(!(index < [self.movies count]))
return;

} while(curY - (COVER_HEIGHT + coverSpace) < dirtyRect.origin.y + dirtyRect.size.height);
}

- (BOOL)isFlipped {
return YES;
}

#pragma mark Private Methods
- (void)frameDidChange {

}

- (CGFloat)coverSpaceForMoviesPerLine:(NSUInteger *)n {
// x = number of covers
// w = view width
// m = cover width
// y = the space
//
// w - (mx)
// f(x) = --------
// x + 1

CGFloat m = COVER_WIDTH;
CGFloat w = [self bounds].size.width;

register NSUInteger x = 1;
CGFloat space;
while(1) {
space = ((w-(m*x)) / ( x + 1.0));
if(space < COVER_SPACE_MIN) {
x--;
space = ((w - (m*x)) / (x + 1.0));
break;
}
x++;
}

if(n) *n = x;
return space;
}

#pragma mark Properties
@synthesize movies=_movies;
- (void)setMovies:(NSArray *)ar {

if(ar != _movies) {
[_movies release];
_movies = [ar retain];

// Update frame size
NSUInteger m;
CGFloat space = [self coverSpaceForMoviesPerLine:&m];
NSUInteger lines = [ar count] / m;
CGFloat height = (COVER_HEIGHT + space) * ((CGFloat)lines) + space;
CGFloat width = [self frame].size.width;
NSRect frame = [self frame];
frame.size = NSMakeSize(width, height);
[self setFrame:frame];
[self setNeedsDisplay:YES];
}
}
@end

在这里您可以找到正在运行的应用程序的屏幕截图: Screenshot

如果有人能告诉我我做错了什么,我将非常感激!

谢谢你,ief2

编辑:不要介意错误的标题,我给文件命名时犯了错误:-)

最佳答案

在我看来,你计算 X 坐标的方式是错误的。行首处的间距是两倍,行尾处没有空格。因此,如果您从 curX 中减去一个空格,您将得到正确的结果:

curX = (rowIndex - 1) * (COVER_WIDTH + coverSpace);

而且您的代码比需要的更复杂。例如,您实际上并不需要 coverSpaceForMoviesPerLine: 中的循环,并且 drawRect: 中的循环也可以简化(同时提高效率)。

关于objective-c - 在 Cocoa 中绘图,xy 值错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4156704/

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