2009-09-08 3 views
7

У меня есть NSMenu, выходящий из NSStatusItem, используя popUpStatusItemMenu. Эти NSMenuItems показывают множество разных ссылок, и каждый из них связан с setAction: с методом openLink: для цели. Эта схема работает отлично в течение длительного времени. Пользователь выбирает ссылку из меню, а метод openLink: затем обрабатывает ее.Пользовательский NSView в NSMenuItem не принимает события мыши

К сожалению, я недавно решил поэкспериментировать с использованием метода setView: NSMenuItem для обеспечения более удобного интерфейса/slicker. В принципе, я просто прекратил настройку заголовка, создал NSMenuItem, а затем использовал setView: для отображения пользовательского представления. Это отлично работает, элементы меню выглядят великолепно, и отображается мое пользовательское представление.

Однако, когда пользователь выбирает пункт меню и отпускает мышь, действие больше не работает (т. Е. OpenLink: не вызывается). Если я просто просто прокомментирую вызов setView:, то действия снова работают (конечно, элементы меню пустые, но действие выполняется правильно). Поэтому мой первый вопрос заключается в том, почему установка представления нарушает действие NSMenuItem.

Без проблем, я думал, я исправлю это, обнаружив событие mouseUp в своем пользовательском представлении и вызывая метод действия оттуда. Я добавил этот метод к своему таможне:

- (void)mouseUp:(NSEvent *)theEvent { 
    NSLog(@"in mouseUp"); 
    } 

Нет кубиков! Этот метод никогда не вызывается.

Я могу установить отслеживание и получить mouseEntered: события. Я поставил несколько тестов в моей обычной mouseEntered следующим образом:

if ([[self window] ignoresMouseEvents]) { NSLog(@"ignoring mouse events"); } 
else { NSLog(@"not ignoring mouse events"); } 
if ([[self window] canBecomeKeyWindow]) { dNSLog((@"canBecomeKeyWindow")); } 
else { NSLog(@"not canBecomeKeyWindow"); } 
if ([[self window] isKeyWindow]) { dNSLog((@"isKeyWindow")); } 
else { NSLog(@"not isKeyWindow"); } 

И получили следующие ответы:

not ignoring mouse events 
canBecomeKeyWindow 
not isKeyWindow 

Является ли это проблемой? "not isKeyWindow"? Предположительно, это плохо, потому что в документах Apple говорится: «Если пользователь нажимает на представление, которого нет в ключевом окне, по умолчанию окно выводится вперед и делает ключ, но событие мыши не отправляется». Но должен быть способ обнаружить эти события. КАК?

Добавление:

[[self window] makeKeyWindow]; 

не имеет никакого эффекта, несмотря на то, что canBecomeKeyWindow да.

+0

Существует больше информации об этой проблеме на открытом радаром: http://openradar.appspot.com/7128269 Существует также утверждал, обходной путь, но я не могу сделать обходной работы. В основном окно просто отказывается стать ключевым, хотя оно сообщает canBecomeKey. – Dennis

+0

Привет, Я столкнулся с той же проблемой, есть ли у вас какие-либо успехи? Я пробовал несколько способов, чтобы решить проблему, я нашел одно обходное решение, но его ужасное уродство, и после отображения пункта меню состояния меню не подсвечивается, но меню отображается и полностью функционально. Я установил меню для элемента статуса в nil и вручную управлял всплывающим меню. Если приложение активно, я просто вызываю метод всплывающего меню, если я не посылаю сообщение о действительном приложении, а в обратном вызове я открываю меню. Вот какой код. Опять его ужасный и уродливый. http://gist.github.com/224275 – iafonov

+0

Я должен сказать, что код Ифафонова - БОЛЬШОЕ! Хотя год назад !!! Хотя код кажется неуместным. Благодаря! Он разрешает все проблемы, связанные с NSVIew, NSTextEdit в NSMenuItem. Сначала NSTextEdit (в NSMenuItem) не работает нормально, не может получать нажатия клавиш, а мышь не меняется, теперь все работает замечательно !!! Нет acceptsFirstResponder, No self window makeFirstResponder: xxx, Just iafonov'code. Это способ всплывающего меню, что имеет значение. http://gist.github.com/224275 – user377808

ответ

9

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

- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent 
{ 
    return YES; 
} 
+1

Работал, спасибо! – Vojto

4

Я добавил этот метод, чтобы мой пользовательский взгляд, и теперь все прекрасно работает:

- (void)viewDidMoveToWindow { 
    [[self window] becomeKeyWindow]; 
} 

Надеется, что это помогает!

12

Добавить этот метод в пользовательских NSView, и он будет нормально работать с событиями мыши

- (void)mouseUp:(NSEvent*) event { 
    NSMenuItem* mitem = [self enclosingMenuItem]; 
    NSMenu* m = [mitem menu]; 
    [m cancelTracking]; 
    [m performActionForItemAtIndex: [m indexOfItem: mitem]]; 
} 

но у меня возникают проблемы с keyhandling, если вы решили эту проблему, может быть, вы можете пойти на мой вопрос и помочь мне немного.

+0

Это решение для меня! Благодаря! – kdbdallas

+0

Вау, я потратил полдня, пытаясь понять это. благодаря – Cory

-1

Недавно мне нужно было показать пользовательский вид для NSStatusItem, показать обычный NSMenu при нажатии на него и поддержку операций перетаскивания на значке состояния.

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

Надеюсь, это поможет другим людям.

-1

См. Пример кода от Apple под именем CustomMenus Там вы найдете хороший пример в классе ImagePickerMenuItemView.

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