0

IBのスクロールビューでレイヤーのチェックマークをクリックして、レイヤーをサポートするように設定されたNSScrollViewがあります。そのスクロールビュー内に NSTableView があります。その NSTableView では、カスタム NSTableRowView を使用して、列間の仕切りに垂直の赤い線を描画します。私の NSTableView には 2 つの列があります。スクロールビューをレイヤーに合わせて設定すると、列の区切りをドラッグして列を広くしたり狭くしたりするたびに、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];
}

列のサイズを変更するときに発生する問題は次のとおりです。

ここに画像の説明を入力

そして、これは、スクロールビューをレイヤーでサポートするように設定していない場合のように見えるはずです:

ここに画像の説明を入力

ありがとう!

4

1 に答える 1

0

1年以上経って、ようやく自分の質問に対する適切な答えを見つけました。

トリックは、NSTableColumn のサイズが変更されているときに、表示される行のリスト内のすべての行で setNeedsDisplay を呼び出すことです。

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 デリゲート メソッドが呼び出されます。NSViewController サブクラスに isResizingTableColumn を実装できます。

列のサイズを変更すると、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 サブクラスでそれを行っていました。これは、1 つのテーブル列のサイズを変更している間に、別の列のサイズも同じように変更していたためです。NSTableView には UITableView のようなフッターの概念がないため、これは 1 行しかない同様に構成された別のテーブルでフッター行をシミュレートしていました。

于 2014-10-15T03:06:47.573 に答える