cocoa - NSButton - 自定义形状按钮的点击测试翻转/悬停

标签 cocoa hittest nsbutton

(针对 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。]

解决步骤:

  1. 向按钮添加一个NSTrackingArea,(至少)NSTrackingMouseEnteredAndExitedNSTrackingMouseMoved选项。

  2. 实现-hitTest:以便对按钮按下进行准确的(例如循环)点击测试。我们不会在这里更改按钮的外观。

  3. 实现-mouseEntered:-mouseExited:

  4. -mouseEntered内进行(圆形)碰撞检测,通过-setImage:相应地更改按钮的外观(或以其​​他方式标记对绘图策略的更改) .)

  5. -mouseExited 上:将按钮的外观设置回默认值。

  6. 但是,-mouseEntered:-mouseExited: 不会连续调用。因此我们还需要实现-mouseMoved:

  7. 但是,我们必须在窗口上调用 -setAcceptsMouseMovedEvents:YES,以便在按钮上调用 -mouseMoved: 方法。

  8. 还将(圆形)碰撞检测和外观更改添加到 -mouseMoved

最佳答案

使用 NSTrackingArea 是正确的方法,对于非矩形形状,您必须添加自定义代码来对自定义几何图形执行 HitTest 。

不清楚为什么当鼠标悬停在形状上方时要连续设置相同的图像?

无论如何,有 mouseMoved: 当鼠标在跟踪区域内移动时收到通知。 不过,请检查文档 - 您可能需要在 View 或窗口上设置一些额外的标志,因为默认行为可能不会发送移动的消息,以免在没有人听的情况下用大量消息阻塞框架..

关于cocoa - NSButton - 自定义形状按钮的点击测试翻转/悬停,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27913615/

相关文章:

Cocoa 连接套件和 FTP

objective-c - 使用一组坐标的外边界构建 MKPolygon - 如何分割落在一条线两侧的坐标?

cocoa - 在 Cocoa OSX 中以编程方式从窗口中删除按钮

objective-c - 如何设置另一个变量/UILabel 变量的引用变量?

objective-c - 将 .plist 文件与 iCloud 同步

cocoa - 如何获取通过 Active Directory 登录 Mac 的用户的域名

ios - 如果它们在表中,我如何使用 hitTest 获取底层 View ?

wpf - 是否可以仅针对右键事件将IsHitTestVisible设置为false?

objective-c - 使用 NSGraphiteControlTint 的按钮

objective-c - 如何有一个按钮转换到 NSView 之外?