【问题标题】:NSImageView tiles inside NSScrollView draw unwanted borders when zoomed outNSScrollView 内的 NSImageView 平铺在缩小时会绘制不需要的边框
【发布时间】:2013-12-24 06:28:01
【问题描述】:

我有一个 NSScrollView,它的 documentView 是一个巨大的 NSView,由许多子 NSImageView 组成,它们在地图中充当图块。 (整个地图是 NSView,由于它比屏幕尺寸大得多,它嵌入在滚动视图中。

我能够以正确的图块位置显示地图,并使用条形/手势滚动。但是..当我启用放大以能够缩放时,会发生以下情况: 不知何故,我假设自动布局在下面添加了瓷砖边框,我不知道如何禁用它们。这些肯定是边界,因为我已经检查了数千次我的图块和子视图的大小相同.. 那么这是从哪里来的呢? 我在 iOS 开发方面有相当多的经验,但对 NSScrollView 完全迷失了(我的委托方法在哪里?)。如何禁用滚动视图的这种行为?

这是我的子视图代码:

- (void)setupSubViews
{
  NSLog(@"--------Creating subviews!-------");
    //first we create the subviews..
    //This is the key part, we traverse from top Left, and since OS X coordinates start at bottom left, we need to invert the rows!
    for (int i=0; i< NUMBER_OF_COLUMNS; i++) {
        for (int j=NUMBER_OF_ROWS-1; j>=0; j--) {
            CGRect frame = CGRectMake(i*256, j*256, 256, 256);
            NSImageView *newView = [[NSImageView alloc] initWithFrame:frame];
            newView.focusRingType = NSFocusRingTypeNone; //I gave this focusRing a try, it didn't work :(

            [self addSubview:newView];
        }
    }

}

这是我将子视图连接到实际图像的地方..

-(void)updateMap:(id)tilesPassed{

    if (downloadFinished) {
        NSLog(@"--------DRAW RECT-------------");
        NSImageView *subView;
        NSInteger idx = 0;

        for (int i =0; i<[self.subviews count]; i++) {
            subView = [self.subviews objectAtIndex:i];
            [subView setAllowsCutCopyPaste:NO];
            [subView setImageFrameStyle:NSImageFrameNone]; //This doesnt work either :(

            MapTile *tile = [tilesArray objectAtIndex:idx];
            subView.image = tile.image;

            idx++;
        }
    }
}

【问题讨论】:

  • 这看起来真的像一个绘图神器,而不是故意绘制的“边框”。根据您的缩放级别,您可能需要制作稍大的图像,以确保像素舍入不会导致您被要求绘制比绘制正确区域所需的稍小的图像。
  • 我的问题是:整个事情需要可缩放(工作)。如果我只使用缩放级别 1,并关闭放大,我看不到线条。它们只会在我放大后出现..

标签: objective-c macos cocoa appkit nsscrollview


【解决方案1】:

您可能不想为此使用子视图。有一个 CALayer 子类正是为此目的:CATiledLayer:https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CATiledLayer_class/Introduction/Introduction.html

使用它,您甚至可以根据放大的程度加载不同的图像图块,就像 Google 地图一样。它将无边界渲染,并且性能将比使用大量子视图更好。子视图很昂贵,层(通常)很便宜。

更新:此示例将使您启动并运行:http://bill.dudney.net/roller/objc/entry/catiledlayer_example

【讨论】:

  • 我得出的结论是 CATiledLayer 可能是解决我的问题的好方法,但我根本无法让它工作(主要是因为缩放),并且没有真正找到好的示例代码也是。Apple 提供的唯一示例是 UIScrollView (PhotoScroller),我需要它用于 Mac OSX... 你能帮我转换那个项目吗?
  • @Cutetare 这篇博文应该可以帮助您启动并运行,并附带一个示例项目:bill.dudney.net/roller/objc/entry/catiledlayer_example
  • Zoom 在该示例中不起作用(相信我,我已经找到/玩过它:P)
  • @Cutetare 对我来说,当我点击它时它会放大。您可能需要更改代码以支持捏合和缩放手势。
  • 但它总是缩放到左下角,而不是鼠标点击。而且我无法让锚点更改为每次鼠标点击
【解决方案2】:

作为一种不使用 CATiledLayer 的快速解决方法,您可以将所有图像拼接为一个图像并将其添加到主视图

下面是拼接2张图片的示例代码:

UIImage *bottomImage = [UIImage imageNamed:@"bottom.png"]; //first image
UIImage *image       = [UIImage imageNamed:@"top.png"]; //foreground image

CGSize newSize = CGSizeMake(209, 260); //size of image view
UIGraphicsBeginImageContext( newSize );

// drawing 1st image
[bottomImage drawInRect:CGRectMake(0,0,newSize.width/2,newSize.height/2)];

// drawing the 2nd image after the 1st
[image drawInRect:CGRectMake(0,newSize.height/2,newSize.width/2,newSize.height/2)] ;

UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

并直接将通过拼接所有平铺图像形成的新图像添加到主视图。

【讨论】:

  • 这个问题是针对 Mac OS X AppKit 的。没有 UIImage ;)
  • 你可以试试这个链接stackoverflow.com/questions/6541764/…
  • 你的这种方法会支持缩放吗?我将如何实现缩放?
  • 你可以使用IKImageView代替NSImageView作为你的主图像视图。将整张图片拼接并嵌入到IKImageView中后,可以进行图片的旋转、缩放、裁剪等操作。
猜你喜欢
  • 2013-04-27
  • 1970-01-01
  • 1970-01-01
  • 2014-09-05
  • 2012-08-24
  • 1970-01-01
  • 2013-12-03
  • 1970-01-01
  • 2020-11-25
相关资源
最近更新 更多