2013-10-11 1 views
0

У меня есть NSScrollView, который настроен на поддержку слоя, щелкнув галочку слоя на scrollview в IB. Внутри этого scrollview у меня есть NSTableView. В этом NSTableView я использую пользовательский NSTableRowView для рисования вертикальной красной линии на разделителе между моими столбцами. Мой NSTableView имеет 2 столбца. Когда мой scrollview установлен для поддержки слоя, всякий раз, когда я перетаскиваю разделитель столбцов, чтобы сделать столбец более широким или узким, drawBackgroundInRect не вызывается, поэтому моя фоновая вертикальная линия не обновляется во время операции перетаскивания.drawBackgroundInRect не вызывается в режиме с поддержкой слоя

Есть ли обходной путь для этого?

Вот код, я использую в drawBackgroundInRect:

- (void)drawBackgroundInRect:(NSRect)dirtyRect { 

[super drawBackgroundInRect:dirtyRect]; 

NSGraphicsContext *nscontext = [NSGraphicsContext currentContext]; 

[nscontext saveGraphicsState]; 

CGContextRef context = (CGContextRef)[nscontext graphicsPort]; 

if (!self.isGroupRowStyle) { 

    CGRect leftColumnRect = [(NSView *)[self viewAtColumn:0] frame]; 
    leftColumnRect.origin.y -= 1.0; 
    leftColumnRect.size.height += 2.0; 
    leftColumnRect.size.width += 1.0; 

    // grey background 

    CGContextSetGrayFillColor(context, 0.98, 1.0); 
    CGContextFillRect(context, leftColumnRect); 

    // draw nice red vertical line 

    CGContextBeginPath(context); 
    CGContextSetRGBStrokeColor(context, 0.6, 0.2, 0.2, 0.3); 

    CGContextMoveToPoint(context, leftColumnRect.size.width + 1.5, 0); 
    CGContextSetLineWidth(context, 1.0); 
    CGContextAddLineToPoint(context, leftColumnRect.size.width + 1.5, leftColumnRect.size.height); 
    CGContextStrokePath(context); 

} 
[nscontext restoreGraphicsState]; 
} 

Вот проблема, которую я получаю при изменении размера колонки:

enter image description here

И это то, что он должен выглядеть например, когда у меня нет моего набора scrollview для поддержки на основе слоев:

enter image description here

Спасибо!

ответ

0

Спустя более года я, наконец, придумал правильный ответ на свой вопрос.

Хитрость заключается в вызове setNeedsDisplay для каждой строки в списке видимых строк при изменении размера NSTableColumn.

Вот код, который я использую в моем NSViewController подкласса:

- (void)tableView:(NSTableView *)tableView isResizingTableColumn:(NSTableColumn *)tableColumn { 
    NSRange range = [tableView rowsInRect:tableView.visibleRect]; 
    for (NSInteger row = range.location; row < (range.location + range.length); row++) { 
     NSTableRowView *rowView = [tableView rowViewAtRow:row makeIfNecessary:NO]; 
     [rowView setNeedsDisplay:YES]; 
    } 
} 

Мой NSTableView имеет, как его заголовок просмотреть мой собственный подкласс NSTableHeaderView. Я установил свой NSViewController в качестве делегата для представления заголовка, чтобы я мог отслеживать, когда пользователь изменяет размер.

TFRecordTableHeaderView.h:

#import <Cocoa/Cocoa.h> 

@protocol TFRecordTableHeaderViewDelegate <NSObject> 
- (void)tableView:(NSTableView *)tableView isResizingTableColumn:(NSTableColumn *)tableColumn; 
@end 

@interface TFRecordTableHeaderView : NSTableHeaderView 
@property (nonatomic, assign) id<TFRecordTableHeaderViewDelegate>delegate; 
@end 

TFRecordTableHeaderView.m:

#import "TFRecordTableHeaderView.h" 

@implementation TFRecordTableHeaderView 

- (id)initWithFrame:(NSRect)frame { 
    self = [super initWithFrame:frame]; 

    if (self) { 
     // Initialization code here. 
    } 

    return self; 
} 

- (void)drawRect:(NSRect)dirtyRect { 
    [super drawRect:dirtyRect]; 
    // do some custom drawing here 
} 

// track resizing of the column as it happens 
// from the docs: If the user is resizing a column in the receiver, returns the index of that column. 

- (NSInteger)resizedColumn { 
    NSInteger columnIndex = [super resizedColumn]; 

    if (columnIndex >= 0) { 
     NSTableColumn *column = [self.tableView.tableColumns objectAtIndex:columnIndex]; 

     if ([self.delegate respondsToSelector:@selector(tableView:isResizingTableColumn:)]) { 
      [self.delegate tableView:self.tableView isResizingTableColumn:column]; 
     } 
    } 

    return columnIndex; 
} 

@end 

Просто установите подкласс NSTableHeaderView с учетом заголовка вашего NSTableView в. Теперь, когда вы перетаскиваете столбец в заголовке, вызывается метод делегирования isResizingTableColumn. Вы можете реализовать isResizingTableColumn в вашем подклассе NSViewController.

Теперь, когда вы изменяете размер столбца, будет вызываться isResizingTableColumn, который получит NSTableRowViews для видимого прямоугольника и отправит setNeedsDisplay. Это приведет к обновлению строк и вызову метода drawBackgroundInRect при перетаскивании. Это, в свою очередь, обновит мои собственные вертикальные линии сетки.

Все это, чтобы избежать рисования вертикальной сетки по верхним сгруппированным строкам в NSTableView. Я думаю, что это должно быть встроено в NSTableView. Это выглядит очень плохо, если в заголовках разделов групп есть текст, и над текстом есть вертикальная линия сетки.

Теперь, когда я об этом думаю, вы могли бы просто сделать это прямо на вашем NSTableHeaderView подкласса:

- (NSInteger)resizedColumn { 
    NSInteger columnIndex = [super resizedColumn]; 

    if (columnIndex >= 0) {   
     NSRange range = [self.tableView rowsInRect:self.tableView.visibleRect]; 
     for (NSInteger row = range.location; row < (range.location + range.length); row++) { 
      NSTableRowView *rowView = [self.tableView rowViewAtRow:row makeIfNecessary:NO]; 
      [rowView setNeedsDisplay:YES]; 
     } 
    } 

    return columnIndex; 
} 

В моем случае я делаю это на моем NSViewController подкласса, потому что в то время как я изменен один столбец таблицы, я был также изменяя другое значение. Это было симуляция строки нижнего колонтитула с другой аналогично настроенной таблицей, в которой было только одна строка, поскольку NSTableView не имеет понятия нижнего колонтитула, такого как UITableView.