(针对 OS X 10.10,最新版本的 Xcode)
我有一个 NSButton 子类。
该按钮需要响应鼠标悬停/悬停,就像一个网络按钮。
按钮需要呈圆形外观。因此,-setImage: 和 -setAlternateImage: 是用圆形图形调用的。
问题 1:当鼠标单击 NSButton 矩形内的任意位置时,NSButton 的默认行为会导致正 HitTest 。这包括按钮圆形区域之外的鼠标单击。
建议的解决方案:覆盖-hitTest:来计算点击距离按钮中心的距离。如果距离 > 按钮的半径,则我们没有有效的点击。
好的,好的。这为我们提供了对圆形按钮上鼠标点击的准确碰撞检测。
问题 2:如何处理鼠标悬停/滚动,并相应地更改按钮的外观。
建议的解决方案:向按钮添加一个 NSTrackingArea,然后覆盖 -mouseEntered: 和 -mouseExited: 这样我们就可以更改按钮当鼠标移动到按钮上时的图像和替代图像。
好的,好的。这适用于矩形。
但是... NSTrackingArea 适用于矩形,而不适用于圆形等任意区域。更糟糕的是,它不尊重 -hitTest:
建议的解决方案:将循环碰撞检测代码添加到 -mouseEntered: 和 -mouseExited:
但是...
-mouseEntered: 和 -mouseExited: 每次按钮进入/退出时仅调用一次,而不是连续调用。这意味着如果鼠标刚刚移动到按钮的矩形区域,但距离不足以进入按钮的圆形区域,则将调用 -mouseEntered: 。但它不会再次被调用,直到调用 -mouseExited: 后。将鼠标进一步移动到圆形区域将不会产生任何效果。 (不会发生翻转。)
即使用这两种方法无法用准确的鼠标位置信息持续更新按钮的状态。
问题:有人知道如何实现悬停和按下非矩形按钮吗?
[编辑 - 已解决感谢 cacau。]
解决步骤:
向按钮添加一个NSTrackingArea,(至少)NSTrackingMouseEnteredAndExited和NSTrackingMouseMoved选项。
实现-hitTest:以便对按钮按下进行准确的(例如循环)点击测试。我们不会在这里更改按钮的外观。
实现-mouseEntered:和-mouseExited:
在-mouseEntered内进行(圆形)碰撞检测,通过-setImage:相应地更改按钮的外观(或以其他方式标记对绘图策略的更改) .)
在-mouseExited 上:将按钮的外观设置回默认值。
但是,-mouseEntered: 和 -mouseExited: 不会连续调用。因此我们还需要实现-mouseMoved:
但是,我们必须在窗口上调用 -setAcceptsMouseMovedEvents:YES,以便在按钮上调用 -mouseMoved: 方法。
还将(圆形)碰撞检测和外观更改添加到 -mouseMoved。
最佳答案
使用 NSTrackingArea
是正确的方法,对于非矩形形状,您必须添加自定义代码来对自定义几何图形执行 HitTest 。
不清楚为什么当鼠标悬停在形状上方时要连续设置相同的图像?
无论如何,有 mouseMoved
: 当鼠标在跟踪区域内移动时收到通知。
不过,请检查文档 - 您可能需要在 View 或窗口上设置一些额外的标志,因为默认行为可能不会发送移动的消息,以免在没有人听的情况下用大量消息阻塞框架..
关于cocoa - NSButton - 自定义形状按钮的点击测试翻转/悬停,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27913615/