2011-12-09 24 views
8

これは私の最初の質問です。可能な限り明確にするようにします。NSTableView:選択した行の前後にカスタムセパレータを描画する方法

ビューベースのNSTableViewで選択した行にカスタムグラデーションを描画し、微妙なエフェクトを追加したいとします。そのためには、選択した行の前後にあるグリッド線の色を暗くする必要があります(例についてはhereを参照してください)。私は(フラグとしてisSelected方法を使用して)選択された行のカスタム区切り線を描画するNSTableRowViewdrawSeparatorInRect:メソッドをオーバーライドしているが、私は/ Iは下部に線を引くため(一方の下/上に同じ操作を行うことができません上)。

表示手順が同じ順序に従っていないため、暗いセパレータ行を描画する必要があるということを最も近い行に伝えるためにいくつかの方法を試しました(私はdrawSeparatorInRect:のNSLogsでチェックしました。この順序の変更を少しスクロールします)。だから、時には(ほとんどの場合、スクロールした後)行が選択された行の前に描画されるので、暗い色を使用する必要があることはわかりません(この時点では、選択行はまだ選択されていません。何が起こっているのか理解していない)。

私が試した事のいくつか:選択された行のdrawSeparatorInRect:方法において

  1. 、Iは兄弟ビュー([superview subviews])にアクセスし、再びそれ自体を描画するために次/前のものを強制的に試みました。
  2. サブクラスNSTableViewより、selectedIndexesが変更されたときに最も近い行を直接変更します。
  3. drawSeparatorInRect:メソッドの中から選択された行の外側の線を描くと、hereと表示されます。

Iこの有した注:次/前のいずれかが選択されているかどうかを尋ねる行ビューを、フラグclosestRowIsSelectedまたは外部「力」の方法暗色呼び出します。

は、私が今持っていることは...選択された行は、両方の上部と下部の境界線を描画しますので、そのうちの一つは、次/前の行ラインに一緒に配置されていることであるそれは微妙だが、それはまだそこに。

どんな助力もうまく受け取ります。

ありがとうございます。

問題がないので、私は、私は思う...ので、私は見るには何もない(それだけで赤い色で[NSBezierPath fillRect:rect]を呼び出す)任意のコードを投稿しませんでした。

答えて

12

私もこれを試してみました。drawSeparatorInRect:は実際には、上の区切り線(前の行の下区切り線と同じです)の位置として下区切り線を描くことができます(上の)行のclipRectを返します。次のように:

- (void)drawSeparatorInRect:(NSRect)dirtyRect 
{ 
    // Define our drawing colors 
    NSColor *normalColor = [NSColor colorWithCalibratedWhite:0.76 alpha:1.0]; // Default separator color 
    NSColor *selectedTopColor = [NSColor colorWithCalibratedWhite:0.60 alpha:1.0]; // Color of the top separator line of selected row 
    NSColor *selectedBottomColor = [NSColor colorWithCalibratedWhite:0.60 alpha:1.0]; // Color of the bottom separator line of selected row 

    // Define coordinates of separator line 
    NSRect drawingRect = [self frame]; // Ignore dirtyRect 
    drawingRect.origin.y = drawingRect.size.height - 1.0; 
    drawingRect.size.height = 1.0; // Height of the separator line we're going to draw at the bottom of the row 

    // Get the table view and info on row index numbers 
    NSTableView *tableView = (NSTableView*)[self superview]; // The table view the row is part of 
    NSInteger selectedRowNumber = [tableView selectedRow]; 
    NSInteger ownRowNumber = [tableView rowForView:self]; 

    // Set the color of the separator line 
    [normalColor set]; // Default 
    if (([self isSelected]) && ((selectedRowNumber + 1) < [tableView numberOfRows])) [selectedBottomColor set]; // If the row is selected, use selectedBottomColor 
    if ((![self isSelected]) && (selectedRowNumber > 0) && (ownRowNumber == (selectedRowNumber-1))) [selectedTopColor set]; // If the row is followed by the selected row, draw its bottom separator line in selectedTopColor 

    // Draw separator line 
    NSRectFill (drawingRect); 

    // If the row is selected, tell the preceding row to redraw its bottom separator line (which is also the top line of the selected row) 
    if (([self isSelected]) && (selectedRowNumber > 0)) [tableView setNeedsDisplayInRect:[tableView rectOfRow:selectedRowNumber-1]]; 
} 

この方法は、(のみ)、自身の下の区切り線を描画します

はしかし、私はそれがNSTableRowViewをサブクラス化し、drawSeparatorInRectを持つことで取り組みました。選択された行であれば、デフォルトの色ではなく強調表示された行を描画し、選択行の先頭のセパレータ行と同じセパレータ行を再描画するよう前の行に指示します。

この作業を行うには、選択した行の上にある行が選択範囲を移動したら、その下の区切り線を再描画する必要があります。 IはNSTableViewのデリゲートでは、この方法を有することによって、これを達成する:

// Tell the row above the row which is going to loose the selection to redraw its bottom separator line 
- (BOOL)selectionShouldChangeInTableView:(NSTableView *)aTableView 
{ 
    NSInteger selectedRowNumber = [aTableView selectedRow]; 
    if (selectedRowNumber > 0) { 
    [aTableView setNeedsDisplayInRect:[aTableView rectOfRow:selectedRowNumber-1]]; 
    } 
    return YES; 
} 

このデリゲートメソッドは、その区切り線を再描画することが選択された行の上の行を伝えます。選択が変更される直前に呼び出されます。

+0

実際にAppleのドキュメントは正しいと分かりました。NSTableRowViewのデフォルトの動作は、行の一番下ではなく、行の下に区切り線を描画することです。上記のコードサンプルを編集しました。 – Tim

+0

ありがとう、私がやろうとしていることは確かです。しかし、私が行を選択するか、またはテーブルビューをスクロールするたびに、前回選択された行がそれ自身を複数回再描画するため、非常に太字のテキストやその他の奇妙なエフェクトが生成されます。私は何か見落としてますか? –

+0

私はそれを私の古いコードと完全に連動させました。しかし、 'drawSeparatorInRect:'メソッドの最後にある先行するセルビューを強制的にドラッグするコードを、選択された新しい行を与えるデリゲートメソッドに移動しました( 'tableView:shouldSelectRow:'を使用しました) 。再度、あなたの援助に感謝します。 –

関連する問題