0

我正在尝试使用ArrayControllerBindings设置带有自定义单元格的NSTableView。为此,我向自定义单元格添加了一个子视图。数据连接似乎有点工作。虽然,似乎有一个我无法解决的重绘问题。当我加载应用程序时,只渲染了一些单元格。当我滚动浏览行或选择一个时,渲染会发生变化。

在 github 上创建了一个示例项目来说明问题所在。

截屏

可以在此处找到单元格渲染的实际源代码:

// CustomCell.m
- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {

  if (![m_view superview]) {
    [controlView addSubview:m_view];
  }

  // The array controller only gets wrapped data items pack by the NSObjectTransformer.
  // Therefore, objectValue returns a NSObjectWrapper.
  // Unpack the wrapper to retreive the data item.
  DataItem* dataItem = [(NSObjectWrapper*)[self objectValue] original];
  [[m_view name] setStringValue:dataItem.name];
  [[m_view occupation] setStringValue:dataItem.occupation];
  [m_view setFrame:cellFrame];
}

似乎父母controlView没有重绘。我可以以某种方式强迫它吗?

4

2 回答 2

3

这几乎可以肯定不是这样做的最佳实践方式,我稍后会解释原因:但是,它似乎确实有效。将您的单元格类的drawInteriorWithFrame:inView:方法替换为以下内容:

- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
    DataItem* dataItem = [(NSObjectWrapper*)[self objectValue] original];
    [[m_view name] setStringValue:dataItem.name];
    [[m_view occupation] setStringValue:dataItem.occupation];
    [m_view setFrame:cellFrame];

    NSData *d = [m_view dataWithPDFInsideRect:[m_view bounds]];
    NSImage *i = [[NSImage alloc] initWithData:d];
    [i setFlipped:YES];

    [i drawInRect:cellFrame fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
}

问题是整个表只创建了一个 NSCell。这就是单元格的工作方式:表格视图创建一个单元格,然后调用 setObject... 然后调用 drawInterior... 一遍又一遍地让单元格绘制整个表格。从效率的角度来看,这很好(NSCell 类是在 25mhz 是一台快速计算机时设计的,因此它旨在最大限度地减少对象分配的数量),但在这里会产生问题。

在您的代码中,您使用值填充视图,并设置其框架,如果需要,将其添加为表视图的子视图。但是,由于您只有一个 NSCell 实例,因此只能有一个视图:您获取了您拥有的单个视图,只是将它移到了表格的行中。

要正确执行此操作,您需要一些数据结构来跟踪您作为 NSTableView 的子视图添加的所有视图,并且当单元格在 drawInterior... 方法中更新一个时,您需要查找正确的那个是和更新那个。您还需要在代码中分配所有这些视图(或者至少将视图移动到可以加载多个副本的单独笔尖),因为您的笔尖中只有一个,并且复制视图是一种痛苦。

我写的代码很杂乱,因为它效率很低。我所做的是每次视图需要绘制时,我将视图绘制到屏幕外图像缓冲区中,然后将缓冲区绘制到表格视图中的正确位置。这样做,我避免了只有一个视图的问题,因为代码只是在需要时获取并绘制其内容的新副本。 在此处输入图像描述

于 2011-05-10T13:39:27.783 回答
0

编辑:请参阅我的其他答案以获取解释

你实施了copyWithZone:吗?您需要确保以该方法复制或重新创建视图,否则不同的单元格最终将共享一个视图(因为 NSTableView 复制其单元格)。

于 2011-05-10T09:02:41.773 回答