【问题标题】:How do I draw a grid of images in Cocoa and export it to a PDF?如何在 Cocoa 中绘制图像网格并将其导出为 PDF?
【发布时间】:2014-05-25 06:22:45
【问题描述】:

我正在制作一个工具,该工具将从 .csv 中提取数据并在 Cocoa 中创建带有标题 [如“This”] 的图像网格,然后将其导出为 PDF。我不需要实际显示视图,只需保存一个文件。作为一个编程绘图的初学者,我对这个过程有一些疑问:

  • 我应该使用什么类?我假设NSView,但就像我说的我以前从未这样做过,所以我不确定。

  • 我是否需要为每个对象指定像素坐标,或者我可以使每个对象以某种方式相对于另一个对象?

  • 如何为视图创建单独的页面?

请记住,我阅读了 Apple 指南,虽然其中有一些有用的花絮,但总的来说,我很难理解。如果有人可以用外行的方式解释我需要知道的内容,将不胜感激!提前谢谢你。

【问题讨论】:

  • 在提出具体问题之前,您不认为您应该阅读有关 Objective-C 编程的书籍或更多内容吗?
  • 我实际上已经读过一本关于 Objective-C 的书,但那本书并没有过多地介绍 Cocoa。我也打算阅读 Cocoa,但我有一个朋友在两周内需要我的程序。这就是我问的主要原因——我已经编程近 4 年了;我最终可以自己学习如何做到这一点,但在 6 月之前我没有足够的空闲时间这样做。

标签: objective-c macos cocoa pdf nsview


【解决方案1】:

看看NSCollectionView

概览

NSCollectionView 类将内容数组显示为一个网格 意见。使用 NSCollectionViewItem 类指定视图 这使得加载包含视图的 nib 变得容易,并支持 绑定

有很多教程。 其中:

Cocoa Programming L42 - NSCollectionViewApples own quick guide to Collection Views

也许还可以看看NSDocuments

概览

NSDocument 抽象类定义了 OS X 的接口 文件。文档是可以在内部表示数据的对象 显示在一个窗口中,可以读取数据和写入数据 文件或文件包。文档创建和管理一个或多个窗口 控制器,然后由文档控制器管理。 文档响应第一响应者操作消息以保存、恢复、 并打印他们的数据。

从概念上讲,文档是信息主体的容器 由存储在磁盘文件中的名称标识。在这个 但是,从某种意义上说,文档与文件不同,而是 内存中拥有和管理文档数据的对象。在里面 AppKit 的上下文,文档是自定义 NSDocument 的实例 知道如何在一个或多个内部表示的子类 格式,在窗口中显示的持久数据。

文档可以从文件中读取该数据并将其写入文件。它 也是许多与相关的菜单命令的第一响应者目标 文档,例如保存、还原和打印。一个文档管理它的 窗口的编辑状态并设置为执行撤消和重做 操作。当窗口关闭时,在 窗口委托批准关闭。

NSDocument 是三个 AppKit 类之一,它建立了一个 基于文档的应用程序的架构基础(其他是 NSDocumentController 和 NSWindowController)。

【讨论】:

    【解决方案2】:

    几天前想通了,以为我会回来为其他有相同问题的人回答。

    我应该使用什么类?我假设NSView,但就像我说的我以前从未这样做过,所以我不确定。

    NSView其实就是我用来绘制每一页的类。

    我是否需要为每个对象指定像素坐标,或者我可以让每个对象以某种方式相对于另一个对象?

    我最终为网格上的每个图像(加上其标题)指定了像素坐标,但是一旦我了解了 8.50 x 11 英寸页面的大小(以磅为单位),就很容易计算出它们应该放置的位置。下一个挑战是将它们绘制在for 循环中,而不是必须显式声明每个可能的NSRect。这是我在drawRect 中的代码:

    // Declared elsewhere: constants for horizontal/vertical spacing,
    // the width/height for an image, and a value for what row the image
    // should be drawn on
    for (int i = 0; i < [_people count]; i++) {
        float horizontalPoint = 0.0; // What column should the image be in?
    
        if (i % 2 != 0) { // Is i odd? (i.e. Should the image be in the right column?)
            horizontalPoint += (imageWidth + horizontalSpace); // Push it to the right
        }
    
        NSRect imageRect = NSMakeRect(horizontalSpace + horizontalPoint, verticalSpace + verticalPoint,
                                  imageWidth, imageHeight);
    
        // Draw the image with imageRect
    
        if (i % 2 != 0) { // Is i odd? (i.e. Is the current row drawn?)
            verticalPoint = (imageRect.origin.y + imageRect.size.height); // Push the row down
        }
    }
    

    我确实意识到我本可以更有效地编写代码(例如,为 i % 2 != 0 制作一个 BOOL),但我急于完成整个项目,因为我需要它的朋友在截止日期前。

    如何为视图创建单独的页面?

    通过谷歌搜索,我找到了this SO answer。但是,除非我有一个将所有页面连接在一起的大视图,否则这是行不通的。我想出了一个方法来做到这一点:

    // Get an array of arrays containing 1-6 JANPerson objects each using data from a parsed in .csv
    NSArray *paginatedPeople = [JANGridView paginatedPeople:people];
    int pages = [JANGridView numberOfPages:people];
    
    // Create a custom JANFlippedView (just an NSView subclass overriding isFlipped to YES)
    // This will hold all of our pages, so the height should be the # of pages * the size of one page
    JANFlippedView *view = [[JANFlippedView alloc] initWithFrame:NSMakeRect(0, 0, 612, 792 * pages)];
    
    for (int i = 0; i < [paginatedPeople count]; i++) { // Iterate through each page
        // Create a custom JANGridView with an array of people to draw on a grid
        JANGridView *gridView = [[JANGridView alloc] initWithFrame:NSMakeRect(0, 0, 612, 792) people:paginatedPeople[i]];
    
        // Push the view's frame down by 792 points for each page drawn already
        // and add it to the main view
        gridView.frame = NSMakeRect(0, 792 * i, gridView.frame.size.width, gridView.frame.size.height);
        [view addSubview:gridView];
    }
    

    如果这对任何人来说难以理解,我深表歉意;我更擅长谈论我的过程而不是写作!如果有不清楚的地方,我欢迎任何人寻求帮助,或者如果他们可以做得更好,请编辑。

    【讨论】:

      【解决方案3】:

      NsView;那么这是一个 Mac 应用程序吗?

      CGPointMake 返回具有指定坐标的点。即使用矩阵将图像放置在屏幕上的特定位置,即

      layer.position = CGPointMake ([self view].bounds.size.width /2, [self     view].bounds.size.height /3 );
      

      (这个例子是围绕核心动画(在屏幕上移动对象,所以请不要太字面意思)因此是层属性)

      还有这一行

      layer.bounds= CGRectMake (100,100,1000,1000);
      

      指定一个矩形边界(矩形可以使用我相信的桥填充图像和自定义数据;像这样):

          UIImage *image2 = [[UIImage alloc]initWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"flogo@2x"ofType:@"png"]];
      
          layer.contents = (__bridge id)image2.CGImage;
      

      我还相信 cgdrawrect 类与矩阵(即 (x,x,x,x) 结合使用时)可以像在您的图像中一样绘制自定义矩形。

      但希望你能通过绘制和替换图像来了解我的想法。 Core graphics 框架可能会在这里使用。 (我的整个答案使用core animation 作为参考)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-04-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多