我正在使用基于视图的NSTableView和自定义NSTableRowView。我想通过drawBackgroundInRect使用自定义行背景绘图,基于使用trackingAreas的鼠标位置。目标是为鼠标当前悬停的未选择行绘制自定义背景。
这几乎与WWDC 2011会话中的HoverTableView example相同基于视图的NSTableView Basic到高级。您可以在 Mail,Contacts&日历系统偏好设置窗格右侧的帐户类型表格视图。
与示例不同,我的表视图中有数千行。除非我快速滚动表格视图(例如,通过触控板进行双指轻弹),否则一切都按照示例中的方式工作。在这种情况下,似乎没有足够快地调用updateTrackingAreas。在鼠标下滚动的行会突出显示,但不会通知鼠标离开其跟踪区域,因此会保持突出显示。结果是显示鼠标悬停突出显示的多行,并且由于重用队列,这些将滚动到表视图的一端并重新出现在另一端(当然,不同的数据)仍然突出显示,就好像它们被重叠一样。滚动慢慢消除了这个问题;但考虑到我希望滚动成千上万行,慢慢滚动并不是预期的用户行为。
我尝试过NSTrackingAreaOptions的各种组合无济于事,现在我很难过。有任何关于解决这个问题的建议将不胜感激。
答案 0 :(得分:2)
我认为这个问题的答案是“你不能”,即快速滚动updateTrackingAreas
中NSTableRowView
的{{1}}在运行循环中不能足够快地发生依靠它来确定指针是否在行视图内。再次,请参阅the HoverTableView example code,了解NSTableView
的使用位置。
我认为我有一个合适的解决方案。我注意到Twitter for Mac(RIP)具有鼠标移动视图,鼠标移动但在滚动时消失,非常类似于我希望实现的鼠标移动高光。
为了执行此操作,我基本上使我的自定义updateTrackingAreas
有一个委托(我的自定义NSTableRowView
),它会询问是否应该在悬停时突出显示。我为NSTableViewController
使用了自定义NSScrollView
并将其称为
NSTableView
在 [self.contentView setPostsBoundsChangedNotifications:YES];
中,并将其注册为awakeFromNib
作为该通知的观察者。收到该通知后,我的自定义self
会将消息转发给我的NSScrollView
。
当我的NSTableViewController
收到表视图正在滚动的消息时,它会在鼠标悬停时禁用突出显示,如果还没有从先前通知运行的有效计时器,则会触发一个短计时器以重新启用突出显示鼠标悬停一旦滚动停止。作为额外的预防措施,在鼠标悬停时启用和禁用突出显示之间的状态转换时,我的NSTableViewController
使用NSTableViewController
清除enumerateAvailableRowViewsUsingBlock
每个行视图。
不确定这是否是最好的方法,但它可以达到我想要的效果。
答案 1 :(得分:1)
此问题的解决方案如下所述:mouseExited isn't called when mouse leaves trackingArea while scrolling
我的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];
}