Как настроить NSTableView с пользовательской ячейкой, используя подпредставление - PullRequest
0 голосов
/ 04 мая 2011

Я пытаюсь настроить NSTableView с пользовательской ячейкой, используя ArrayController и Bindings .Для этого я добавил подпредставление в пользовательскую ячейку.Подключение к данным, кажется, работает несколько.Хотя, кажется, есть проблема перерисовки, которую я не могу исправить.При загрузке приложения отображаются только некоторые ячейки.Когда я прокручиваю строки или выбираю одну, рендеринг изменяется.

Я создал пример проекта на github , чтобы показать, в чем проблема.

Screenshot

Фактический исходный код для рендеринга ячейки можно найти здесь :

// 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 не перерисовывается.Могу ли я заставить его как-нибудь?

Ответы [ 2 ]

3 голосов
/ 10 мая 2011

Это почти наверняка не лучший способ сделать это, и я объясню почему потом: однако, похоже, это работает.Замените метод 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 был разработан еще тогда, когда 25 МГц был быстрым компьютером, поэтому он был нацелен на минимизацию количества распределений объектов), но здесь возникают проблемы.

В вашем коде вы заполняетепросмотрите значения и установите его фрейм, добавив его как подпредставление табличного представления при необходимости.Однако, поскольку у вас есть только один экземпляр NSCell, может быть только одно представление: вы взяли одно имеющееся у вас представление и просто переместили его вниз по строкам таблицы.

Чтобы сделать это правильно,вам потребуется некоторая структура данных для отслеживания всех представлений, которые вы добавили в качестве подпредставлений вашего NSTableView, а когда ячейка обновляет один в методе drawInterior…, вам нужно будет найти, какой из них был правильный, и обновить его.Вам также нужно было бы выделить все эти представления в коде (или, по крайней мере, переместить представление в отдельное перо, в которое можно было бы загрузить несколько копий), потому что, поскольку у вас есть только одно перо, копирование представленияболь.

Код, который я написал, - это клочок, поскольку он действительно неэффективен.То, что я делал, было каждый раз, когда нужно рисовать представление, я рисовал представление в буфере изображения вне экрана, а затем перетаскивал буфер в правильное место в представлении таблицы.При этом я избежал проблемы наличия только одного представления, поскольку код просто берет и рисует новую копию своего содержимого всякий раз, когда это необходимо.enter image description here

0 голосов
/ 10 мая 2011

РЕДАКТИРОВАТЬ: см. Мой другой ответ для объяснения

Вы реализовали copyWithZone:?Вам нужно будет убедиться, что вы копируете или воссоздаете свое представление в этом методе, иначе разные ячейки в конечном итоге будут совместно использовать представление (потому что NSTableView копирует свои ячейки).

...