Как сделать прозрачный подкласс NSView обрабатывать события мыши? - PullRequest
11 голосов
/ 12 января 2009

проблема

у меня прозрачный NSView на прозрачном NSWindow. Метод drawRect: представления отображает некоторое содержимое (NSImage s, NSBezierPath s и NSString s) в представлении, но оставляет его части прозрачными.

Нажатие на области вида, которые были нарисованы, вызывает обычные методы обработки событий мыши (mouseDown: и mouseUp:).

Нажатие на прозрачные области дает фокус любому окну, находящемуся за моим прозрачным окном.

Я бы хотел, чтобы части прозрачной области можно было щелкать , чтобы при случайном щелчке между элементами, нарисованными на моем виде, окно не теряло фокус.


Решения уже предприняты

  • Переопределение NSView hitTest: метода. Обнаружено, что hitTest: вызывается только при нажатии на непрозрачную область вида.
  • Переопределение NSView метода opaqueAncestor. Обнаружено, что это не вызывается при нажатии на любую часть представления.
  • Заполнение частей прозрачной области с помощью [NSColor clearColor] в методе drawRect: и почти прозрачным цветом, но не совсем прозрачным. Это не имело никакого эффекта.
  • Экспериментировал с классом NSTrackingArea. Похоже, это добавляет поддержку только для методов mouseEntered:, mouseExited:, mouseMoved: и cursorUpdate:, not mouseUp: и mouseDown:.

Ответы [ 7 ]

7 голосов
/ 09 сентября 2012

У меня была такая же проблема. Похоже, [window setIgnoresMouseEvents:NO] сделает это.

(По крайней мере, на Льве. См. http://www.cocoabuilder.com/archive/cocoa/306910-lion-breaks-the-ability-to-click-through-transparent-window-areas-when-the-window-is-resizable.html)

5 голосов
/ 12 января 2009

Насколько я знаю, события click для прозрачных частей окон вообще не доставляются в ваше приложение, поэтому ни одно из обычных переопределений цепочки событий (i.e -hitTest :, -sendEvent: и т. Д.) Не будет работать. Единственный способ, который я могу придумать, - использовать Quartz Event Taps, чтобы захватить все щелчки мыши, а затем выяснить, находятся ли они над прозрачной областью вашего окна вручную. Откровенно говоря, это звучит как огромная PITA за небольшую выгоду.

2 голосов
/ 23 сентября 2009

Джордж: Вы упомянули, что пытались заполнить порции почти, но не совсем прозрачным цветом. В моем тестировании это работает, только если значение альфа выше 0,05, так что вам может повезти с чем-то вроде этого:

[[NSColor colorWithCalibratedRed:0.01 green:0.01 blue:0.01 alpha:0.05] set];

Это безобразный кладж, но он может работать достаточно хорошо, чтобы избежать использования события.

1 голос
/ 21 ноября 2013

Вы можете использовать монитор событий для отслеживания событий за пределами окна / вида. https://developer.apple.com/library/mac/documentation/cocoa/conceptual/eventoverview/MonitoringEvents/MonitoringEvents.html

1 голос
/ 12 января 2009

Вы пытались переопределить

- (NSView *)hitTest:(NSPoint)aPoint 

в вашем подклассе NSView?

0 голосов
/ 30 июля 2016

Вы можете сделать:

NSView* windowContent = [window contentView];
[windowContent setWantsLayer:YES]

Убедиться, что фон прозрачный:

[[windowContent layer] setBackgroundColor:[[NSColor clearColor] CGColor]];

Другой вариант - добавить прозрачное фоновое изображение, которое заполняет contentView.

0 голосов
/ 12 января 2009

Вы можете переопределить метод hitTest в вашем NSView, чтобы он всегда возвращал себя.

В соответствии с документацией NSView , метод hitTest будет возвращать NSView, по которому щелкнул пользователь, или nil, если точка не находится внутри NSView. В этом случае я бы вызвал [super hitTest:], а затем вернул бы текущее представление, только если в противном случае результат будет nil (на случай, если ваше пользовательское представление содержит подпредставления).

- (NSView *)hitTest:(NSPoint)aPoint
{
    NSView * clickedView = [super hitTest:aPoint];
    if (clickedView == nil)
    {
        clickedView = self;
    }

    return clickedView;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...