使用NSButtonCell实例获取自定义NSCell以处理鼠标单击/鼠标事件

时间:2010-06-10 19:39:42

标签: cocoa nstableview nscell nsbuttoncell

好的,我真的很难过这个。我想用一个复选框 NSTextFieldCell结合在一起。复选框很重要 如果鼠标击中框而不是文本,则为ON。我已经完成了 这个,或多或少,但问题是接收鼠标事件,因为 我单击一行中的一个复选框,但所有这些复选框都转到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:......被调用

startTrackingAt:...,continueTracking:...,和stopTracking:.... DO 当我点击“点击区域”复选框

时,不会被调用 在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];
}

3 个答案:

答案 0 :(得分:0)

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

  

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

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

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

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

(我注意到你标记了问题“NSTableViewCell”.AppKit中不存在这样的类。)

  

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

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

虽然UITableView每行使用一个单元格,并且屏幕上的行数与单元格一样多,但NSTableView会为每列使用单个单元格。

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

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

对不起,我无法帮助你一路解决问题(除了我刚刚制作他们的单独栏目建议),但我希望这至少可以帮助你解决问题。< / p>

*它也有一个标题单元格,但这不算数。我正在谈论的“正好一个单元格”是它的数据单元。

答案 1 :(得分: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;
}        

我仍然有一些问题,如果我点击某个地点的复选框点击区域,它没有注册,但或多或​​少有效。

答案 2 :(得分:0)

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

当用户点击复选框时,在NSBrowser委托的浏览器中:setObjectValue:forItem:我得到一个NSBoolean并将我对应的“node”对象的“checked”ivar设置为等于NSBoolean。

在NSBrowser委托的浏览器中:willDisplayCell:atRow:column:方法我调用[browser itemAtIndex:]来获取我的“节点”,并使用节点的“已检查”ivar调用单元格的setState:方法。

查看“ComplexBrowser”Xcode示例项目,了解浏览器委托内容的示例代码。

无论你做什么,我都不建议继承NSBrowserCell。那对我来说是一个巨大的死胡同。

更新2011年8月30日:这在10.5中不起作用。啊。我回到原点。