在NSView中创建网格

Hoo*_*cat 6 grid cocoa objective-c nsview drawrect

我目前有一个NSView绘制网格图案(基本上是水平和垂直线的指南),其想法是用户可以更改网格的间距和网格的颜色.

网格的目的是在排列对象时充当用户的指导.除了一个例外,一切正常.当我NSWindow通过拖动调整大小手柄调整大小时,如果我的网格间距特别小(比如10像素).阻力调整大小变得昏昏欲睡.

drawRect的网格代码如下:

-(void)drawRect:(NSRect)dirtyRect {

    NSRect thisViewSize = [self bounds];

    // Set the line color

    [[NSColor colorWithDeviceRed:0 
                           green:(255/255.0) 
                            blue:(255/255.0) 
                           alpha:1] set];

    // Draw the vertical lines first

    NSBezierPath * verticalLinePath = [NSBezierPath bezierPath];

    int gridWidth = thisViewSize.size.width;
    int gridHeight = thisViewSize.size.height;

    int i;

    while (i < gridWidth)
    {
        i = i + [self currentSpacing];

        NSPoint startPoint = {i,0};
        NSPoint endPoint = {i, gridHeight};

        [verticalLinePath setLineWidth:1];
        [verticalLinePath moveToPoint:startPoint];
        [verticalLinePath lineToPoint:endPoint];
        [verticalLinePath stroke];
    }

    // Draw the horizontal lines

    NSBezierPath * horizontalLinePath = [NSBezierPath bezierPath];

    i = 0;

    while (i < gridHeight)
    {
        i = i + [self currentSpacing];

        NSPoint startPoint = {0,i};
        NSPoint endPoint = {gridWidth, i};

        [horizontalLinePath setLineWidth:1];
        [horizontalLinePath moveToPoint:startPoint];
        [horizontalLinePath lineToPoint:endPoint];

        [horizontalLinePath stroke];
    }
}
Run Code Online (Sandbox Code Playgroud)

我怀疑这完全与我绘制网格的方式有关,我愿意接受有关如何更好地解决问题的建议.

我可以看到效率低下的地方,拖动调整大小是在调整大小时NSWindow不断调用drawRect此视图,并且网格越近,父窗口的每像素拖动计算越多.

我想在窗口的大小调整上隐藏视图,但它感觉不像动态.我希望用户体验非常流畅,没有任何明显的延迟或闪烁.

有没有人对更好或更有效的绘制网格方法有任何想法?

所有的帮助,一如既往,非常感谢.

e.J*_*mes 13

你无意中将Schlemiel引入了你的算法.每次你打电话moveToPoint,并lineToPoint在你的循环,你实际上是增加更多的线路相同的路径,所有这些都将被绘制每次通话时间stroke这条道路上.

这意味着你是第一次画一条线,第二次画两条线,第三次画三条线等等......

一个快速的解决将是通过每一次循环中使用新的路径简单地执行stroke 的循环(与感谢杰森可可的想法):

path = [NSBezierPath path];
while (...)
{
    ...

    [path setLineWidth:1];
    [path moveToPoint:startPoint];  
    [path lineToPoint:endPoint];
}
[path stroke];
Run Code Online (Sandbox Code Playgroud)

更新:另一种方法是避免NSBezierPath完全创建,只需使用 strokeLineFromPoint:toPoint: class方法:

[NSBezierPath setDefaultLineWidth:1];
while (...)
{
    ...
    [NSBezierPath strokeLineFromPoint:startPoint toPoint:endPoint];
}
Run Code Online (Sandbox Code Playgroud)

更新#2:到目前为止,我对这些方法做了一些基本的基准测试.我正在使用一个800x600像素的窗口,十个像素的网格间距,我有可可重绘窗口一千次,从800x600扩展到900x700再回来.在我的2GHz Core Duo Intel MacBook上运行,我看到以下几次:

Original method posted in question:  206.53 seconds  
Calling stroke after the loops:       16.68 seconds  
New path each time through the loop:  16.68 seconds  
Using strokeLineFromPoint:toPoint:    16.68 seconds  
Run Code Online (Sandbox Code Playgroud)

这意味着减速完全是由重复造成的,而且几项微观改进中的任何一项都没有做到实际加速.这不应该是一个惊喜,因为屏幕上像素的实际绘制(几乎总是)比简单的循环和数学运算更加处理器密集.

要吸取的教训:

  1. 隐藏的施莱米尔斯真的可以放慢速度.
  2. 始终在进行不必要的优化之前分析代码