1

OK、私はこれに本当に困惑しています。NSTextFieldCell を組み合わせたチェックボックスを作りたいです。マウスがテキストではなくボックスに当たった場合、チェックボックスがオンになることが重要です。私は多かれ少なかれこれを達成しましたが、1つのチェックボックスを続けてクリックしたため、問題はマウスイベントを受け取りましたが、それらはすべてNSOnStateに変わりました。これを機能させるために、私が行ったことと、失敗したさまざまな試みを示します。

だから、これは私がこれまでにやった方法です:

ヘッダ:

@interface MyCheckboxCellToo : NSTextFieldCell {
   NSButtonCell *_checkboxCell;
}

実装:

- (NSUInteger)hitTestForEvent:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView {
    NSPoint point = [controlView convertPoint:[event locationInWindow] fromView:nil];
    NSLog(@"%@", NSStringFromPoint(point));

    NSRect checkFrame;
    NSDivideRect(cellFrame, &checkFrame, &cellFrame, cellFrame.size.height/*3 + [[_checkboxCell image] size].width*/, NSMinXEdge);

    if (NSMouseInRect(point, checkFrame, [controlView isFlipped])) {
        // the checkbox, or the small region around it, was hit. so let's flip the state
        NSCellStateValue checkState = ([_checkboxCell state] == NSOnState) ? NSOffState:NSOnState;
        [self setState:checkState];
        [_checkboxCell setState:checkState];
        [controlView setNeedsDisplay:YES];
        return NSCellHitTrackableArea;
    }        
    return [super hitTestForEvent:event inRect:cellFrame ofView:controlView];    
}

私はおそらくやるべきではないことを知っています:

   [self setState:checkState];
   [_checkboxCell setState:checkState];
   [controlView setNeedsDisplay:YES];

そこに...結果は、すべてのすべてのチェックボックスがNSOnStateになるためです。細胞を再利用しているからでしょうか。ImageAndTextCell が同じテーブルビューに異なる画像を持つことができるのはなぜですか? マウスイベントを処理するにはどうすればよいですか?

私が試してみました:

- (BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame
ofView:(NSView *)controlView untilMouseUp:(BOOL)untilMouseUp {
   NSLog(@"%s %@", _cmd, theEvent);
   return [_checkboxCell trackMouse:theEvent inRect:cellFrame
ofView:controlView untilMouseUp:untilMouseUp];
//    return YES;
//    return [super trackMouse:theEvent inRect:cellFrame
ofView:controlView untilMouseUp:untilMouseUp];
}

- (BOOL)startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView {
   NSLog(@"%s %@", _cmd, NSStringFromPoint(startPoint));
   return [super startTrackingAt:startPoint inView:controlView];
}

- (BOOL)continueTracking:(NSPoint)lastPoint at:(NSPoint)currentPoint
inView:(NSView *)controlView {
   NSLog(@"%s %@", _cmd, NSStringFromPoint(currentPoint));
   return [super continueTracking:lastPoint at:currentPoint
inView:controlView];
}

- (void)stopTracking:(NSPoint)lastPoint at:(NSPoint)stopPoint
inView:(NSView *)controlView mouseIsUp:(BOOL)flag {
   NSLog(@"%s %d %@", _cmd, flag, NSStringFromPoint(stopPoint));
}

trackMouse: ... DOES が呼び出されます

しかし

startTrackingAt:...、continueTracking:...、および stopTracking:.... チェックボックス「ヒット領域」をクリックしても呼び出されません

トラックマウスで:...私は試しました

return [_checkboxCell trackMouse:theEvent inRect:cellFrame ofView:controlView untilMouseUp:untilMouseUp];

return [super trackMouse:theEvent inRect:cellFrame ofView:controlView untilMouseUp:untilMouseUp];

また、チェックボックスによってマウスイベントが処理されるようには見えません。

その単一のチェックボックスを NSOnState にするにはどうすればよいですか? 私はかなり近いことを知っていますが、多くのドキュメントを読んだり、グーグルで検索したりした後、これを解決することに成功していません。

提案やコメントを歓迎します..


OK ここで、オブジェクトの作成と破棄をもう少し示します..

- (id)init {
    if ((self = [super init])) {
        _checkboxCell = [[NSButtonCell alloc] init];
        [_checkboxCell setButtonType:NSSwitchButton];
        [_checkboxCell setTitle:@""];
        [_checkboxCell setTarget:self];
        [_checkboxCell setImagePosition:NSImageLeft];
        [_checkboxCell setControlSize:NSRegularControlSize];

    }
    return self;
}

- copyWithZone:(NSZone *)zone {
    MyCheckboxCellToo *cell = (MyCheckboxCellToo *)[super copyWithZone:zone];
    cell->_checkboxCell = [_checkboxCell copyWithZone:zone];
    return cell;
}

- (void)dealloc {
    [_checkboxCell release];
    [super dealloc];
}
4

3 に答える 3

0

わかりました、これは多かれ少なかれ私の問題を解決するように見えました。

hitForTestEvent: ...

それ以外の

    if (NSMouseInRect(point, checkFrame, [controlView isFlipped])) {
    // the checkbox, or the small region around it, was hit. so let's flip the state
    NSCellStateValue checkState = ([_checkboxCell state] == NSOnState) ? NSOffState:NSOnState;
    [self setState:checkState];
    [_checkboxCell setState:checkState];
    [controlView setNeedsDisplay:YES];
    return NSCellHitTrackableArea;
}        

そのはず:

    if (NSMouseInRect(point, checkFrame, [controlView isFlipped])) {
    [_checkboxCell setState:![_checkboxCell state]];
    return NSCellHitTrackableArea;
}        

特定の場所でチェックボックスのヒットゾーンをクリックすると、登録されませんが、多かれ少なかれこれが機能するという問題がまだいくつかあります。

于 2010-07-02T15:13:57.450 に答える
0

NSTextFieldCell の代わりに NSButtonCell のサブクラスであるカスタム セル クラスを作成しました。クリックがチェックボックスにない場合、hitTestForEvent:inRect:ofView: で 0 を返します。

ユーザーがチェックボックスをクリックすると、NSBrowser デリゲートの browser:setObjectValue:forItem: NSBoolean が取得され、対応する「ノード」オブジェクトの「チェックされた」ivar がその NSBoolean に等しく設定されます。

NSBrowser デリゲートの browser:willDisplayCell:atRow:column: メソッドで、[browser itemAtIndex:] を呼び出して「ノード」を取得し、ノードの「チェック済み」ivar を使用してセルの setState: メソッドを呼び出します。

ブラウザ デリゲートに関するサンプル コードについては、「ComplexBrowser」Xcode サンプル プロジェクトを参照してください。

何をするにしても、NSBrowserCell をサブクラス化することはお勧めしません。それは私にとって大きな行き止まりでした。

2011 年 8 月 30 日更新: これは 10.5 では機能しません。うーん。振り出しに戻りました。

于 2011-02-28T21:47:40.983 に答える
0

質問のhandling-events-in-cells部分に直接答えることはできませんが、これらの部分には答えることができます:

私はおそらくやるべきではないことを知っています:

[self setState:checkState];
[_checkboxCell setState:checkState];
[controlView setNeedsDisplay:YES];

そこに...結果は、すべてのすべてのチェックボックスがNSOnStateになるためです。細胞を再利用しているからでしょうか。

UITableView が UITableViewCells を再利用する方法とは異なる意味で再利用されます。

(質問に「NSTableViewCell」というタグを付けたことに気付きました。そのようなクラスは AppKit に存在しません。)

ImageAndTextCell が同じテーブルビューに異なる画像を持つことができるのはなぜですか?

両方の質問に対する答えは同じです。

UITableView は各行に 1 つのセルを使用し、画面上の行と同じ数のセルを手元に保持しますが、NSTableView はすべての列に単一のセルを使用します。

各列は NSTableColumn オブジェクトとして存在し、各 NSTableColumn には正確に 1 つのセルがあります*。テーブル ビューは、セルのオブジェクト値を、その列と行の交点に指定した値に設定し、境界内の適切な場所に描画するようにセルに指示します。すべての行のその列に対して、同じセルで同じことを行います。

(ここには例外があります。Apple は特定の行に別のセルを使用する機能を追加したためです。また、列がなく別のセルを使用するグループ行を追加したためです。ただし、基本的なメカニズムは同じです。)

解決策を完全に提供できなくて申し訳ありませんが (列を分けて作成するという私の提案は別として)、これが少なくとも部分的に役立つことを願っています。

※ヘッダーセルもありますが、ここではカウントしません。私が話している「正確に 1 つのセル」とは、そのデータ セルです。

于 2010-06-11T06:01:46.930 に答える