1

好吧,我真的被这个难住了。我想制作一个将 NSTextFieldCell 组合在一起的复选框。如果鼠标点击框而不是文本,则复选框打开很重要。我或多或少地完成了这一点,但问题是接收鼠标事件,因为我连续单击一个复选框,但它们都转向 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 可以在同一个 tableview 中有不同的图像?如何处理鼠标事件?

我努力了:

- (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:.... 当我点击复选框“命中区域”时不要被调用

在 trackMouse:... 我试过了

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

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

并且似乎都没有导致复选框处理鼠标事件。

如何让单个复选框进入 NSOnState?我知道我已经很接近了,但是经过大量的文档阅读和谷歌搜索后,我并没有成功解决这个问题。

欢迎提出建议和意见。。


好的,这里有更多显示对象的创建和销毁..

- (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

我创建了一个自定义单元格类,它是 NSButtonCell 而不是 NSTextFieldCell 的子类。如果单击不在复选框上,它在 hitTestForEvent:inRect:ofView: 中返回 0。

当用户单击复选框时,在 NSBrowser 委托的浏览器中: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

我不能直接回答问题的处理事件部分,但我可以回答这些部分:

我知道我可能不应该这样做:

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

在那里...因为结果是每个复选框都进入 NSOnState。这是因为细胞被重复使用了吗?

它们的重用方式与 UITableView 重用 UITableViewCells 的方式不同。

(我注意到您标记了问题“NSTableViewCell”。AppKit 中不存在此类。)

为什么 ImageAndTextCell 可以在同一个 tableview 中有不同的图像?

这两个问题的答案是一样的。

UITableView 为每一行使用一个单元格,并保留与屏幕上的行一样多的单元格,而 NSTableView 为每一列使用一个单元格。

每一列都作为一个 NSTableColumn 对象存在,并且每个 NSTableColumn 都只有一个单元格*。表格视图将单元格的对象值设置为您为该列-行交叉点提供的任何值,然后告诉单元格在其边界内的适当位置进行绘制。对于每一行的那一列,它会对同一个单元格做同样的事情。

(这里有例外,因为 Apple 添加了对特定行使用不同单元格的功能,并且因为他们添加了组行,这些行没有列并使用不同的单元格。但基本机制是相同的。)

很抱歉,我无法一路帮助您找到解决方案(除了我的 just-make-them-separate-columns 建议),但我希望这至少可以部分帮助您。

*它也有一个标题单元格,但这里不计算在内。我所说的“恰好一个单元格”是它的数据单元格。

于 2010-06-11T06:01:46.930 回答
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 回答