(Ориентация на OS X 10.10, последняя версия Xcode)
У меня есть подкласс NSButton.
Кнопка должна реагировать на наведение / наведение курсора мыши, например веб-кнопку.
Кнопка должна иметь форму круга. Соответственно, -setImage: и -setAlternateImage: вызываются с графикой круглой формы.
Проблема 1: поведение NSButton по умолчанию приводит к положительному результату проверки попадания при щелчке мышью в любом месте в пределах поля NSButton. Сюда входят щелчки мышью за пределами круглой области кнопки.
Предлагаемое решение: переопределить -hitTest: для расчета расстояния клика от центра кнопки. Если расстояние> радиуса кнопки, у нас нет действительного щелчка.
Хорошо. Это обеспечивает точное обнаружение столкновений при щелчках мышью по круглым кнопкам.
Проблема 2: как обрабатывать наведение / наведение курсора мыши и соответствующим образом изменять внешний вид кнопки.
Предлагаемое решение: добавьте NSTrackingArea к кнопке, а затем переопределите -mouseEntered: и -mouseExited:, чтобы мы могли изменить изображение кнопки и alternateImage. когда мышь перемещается по кнопке.
Хорошо. Это работает для прямоугольников.
Но ... 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.