3

カスタム NSTableRowView でビューベースの NSTableView を使用しています。trackingAreas を使用してマウスの位置に基づいて、drawBackgroundInRect を介してカスタム行の背景描画を使用したいと思います。目標は、マウスが現在ホバリングしている選択されていない行のカスタム背景を描画することです。

これは、WWDC 2011 セッションのView Based NSTableView Basic to AdvancedのHoverTableView の例とほぼ同じです。右側のアカウント タイプ テーブル ビューの [メール、連絡先、およびカレンダーのシステム環境設定] ペインで、その動作を確認できます。

例とは異なり、テーブル ビューには何千もの行があります。テーブル ビューをすばやくスクロールしない限り (たとえば、トラックパッドを介して 2 本指でフリック)、すべてが例のように機能します。この場合、 updateTrackingAreas が十分に速く呼び出されていないようです。マウスの下でスクロールする行は強調表示されますが、マウスが追跡領域を離れたことは通知されないため、強調表示されたままになります。その結果、マウス オーバー ハイライトを示す複数の行が作成され、再利用キューにより、これらはテーブル ビューの一方の端からスクロールされて、もう一方の端に再表示されます (もちろん、異なるデータを使用して) マウス オーバーのようにハイライトされたままです。 . ゆっくりとスクロールすると、問題が解消されます。しかし、何千もの行をスクロールすることを期待していることを考えると、ゆっくりスクロールすることは期待されるユーザーの動作ではありません。

NSTrackingAreaOptions のさまざまな組み合わせを試してみましたが、うまくいきませんでした。この問題を解決するための提案をいただければ幸いです。

4

2 に答える 2

2

質問に対する答えは「できない」だと思います。つまり、updateTrackingAreas高速NSTableRowViewスクロールでNSTableViewは、ポインターが行ビュー内にあるかどうかを判断するために実行ループに依存するのに十分な速度で一貫して発生しないということです。ここでも、HoverTableView のサンプル コードを参照して、 がどこupdateTrackingAreasで使用されているかを確認してください。

しかし、適切な解決策があると思います。Twitter for Mac ( RIP ) には、マウスを動かすと表示されるがスクロールすると消えるマウスオーバー ビューがあることに気付きました。

これを実行するために、私は基本的にカスタムNSTableRowViewにデリゲート (my custom NSTableViewController) を持たせ、ホバー時に強調表示するかどうかを尋ねます。NSScrollView私は自分のカスタムを使用してNSTableView呼び出しました

    [self.contentView setPostsBoundsChangedNotifications:YES];

また、その通知のオブザーバーとしてawakeFromNib登録しました。self私のテーブルビューがスクロールしていることを意味するその通知を受け取ると、私のカスタムNSScrollViewはメッセージを my に転送しますNSTableViewController

テーブルビューがスクロールしてNSTableViewControllerいるというメッセージを受け取ると、マウスオーバーでの強調表示を無効にし、以前の通知から実行されている有効なタイマーがまだない場合は、短いタイマーを起動して、スクロールが停止したらマウスオーバーで強調表示を再度有効にします. 特別な予防措置として、マウスオーバー時のハイライトの有効化と無効化の間の状態遷移で、すべての行ビューをクリアするためにNSTableViewController使用します。enumerateAvailableRowViewsUsingBlockmouseInside

これが必ずしも最善の方法であるかどうかはわかりませんが、私が望んでいた効果が得られます。

于 2012-09-28T11:08:46.970 に答える
1

この問題の解決方法は次のとおりです。スクロール中にマウスが trackingArea を離れたときに、mouseExited が呼び出されない

私の updateTrackingAreas メソッドは次のようになります。

- (void)updateTrackingAreas {
    if (trackingArea)
        [self removeTrackingArea:trackingArea];

    [trackingArea release];

    trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect
                                                options:NSTrackingInVisibleRect |
                                                        NSTrackingActiveAlways |
                                                        NSTrackingMouseEnteredAndExited
                                                  owner:self
                                               userInfo:nil];

    [self addTrackingArea:trackingArea];

    NSPoint mouseLocation = [[self window] mouseLocationOutsideOfEventStream];
    mouseLocation = [self convertPoint: mouseLocation fromView: nil];

    if (NSPointInRect(mouseLocation, [self bounds]))
        [self mouseEntered:nil];
    else
        [self mouseExited:nil];

    [super updateTrackingAreas];
}
于 2014-05-29T09:07:27.217 に答える