Выделение NSMenuItem с пользовательским представлением? - PullRequest
18 голосов
/ 19 мая 2011

Я создал простой NSStatusBar с NSMenu, установленным в качестве меню. Я также добавил несколько NSMenuItems в это меню, которые работают нормально (включая селекторы и подсветку), но как только я добавляю пользовательское представление (setView :), подсветка не происходит.

CustomMenuItem *menuItem = [[CustomMenuItem alloc] initWithTitle:@"" action:@selector(openPreferences:) keyEquivalent:@""];
[menuItem foo];
[menuItem setTarget:self];
[statusMenu insertItem:menuItem atIndex:0];
[menuItem release];

И мой метод foo:

- (void)foo {
  NSView *view = [[NSView alloc] initWithFrame:CGRectMake(5, 10, 100, 20)];
  [self setView:view];
}

Если я удалю метод setView, он будет выделен.

Я искал и искал и не могу найти способ реализовать / включить это.

Редактировать

Я реализовал выделение, следуя коду в этом вопросе в моем подклассе NSView:

Представление NSMenuItem (экземпляр подкласса NSView) не выделяется при наведении

#define menuItem ([self enclosingMenuItem])

- (void) drawRect: (NSRect) rect {
    BOOL isHighlighted = [menuItem isHighlighted];
    if (isHighlighted) {
        [[NSColor selectedMenuItemColor] set];
        [NSBezierPath fillRect:rect];
    } else {
        [super drawRect: rect];
    }
}

Ответы [ 4 ]

10 голосов
/ 22 января 2012

Вот довольно менее скучная версия выше. Это хорошо сработало для меня. (backgroundColour - это ивар.)

- (void)drawRect:(NSRect)rect
{
    if ([[self enclosingMenuItem] isHighlighted]) {
        [[NSColor selectedMenuItemColor] set];
    } else if (backgroundColour) {
        [backgroundColour set];
    }
    NSRectFill(rect);
}
6 голосов
/ 19 мая 2011

Если вы добавляете вид к элементу меню, этот вид должен рисовать саму подсветку. Боюсь, ты не получишь это бесплатно. Из меню Темы программирования :

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

3 голосов
/ 20 мая 2011

Да, как уже упоминалось ранее, вы должны нарисовать это самостоятельно.Я использую AppKit NSDrawThreePartImage (…) для рисования, а также включаю проверки для использования внешнего вида пользовательского элемента управления (синего или графитового). Чтобы получить изображения, я просто взял их со скриншота (если кто-нибудь знает лучший способ, добавьте комментарий.) Вот фрагмент drawRect моего MenuItemView:

    // draw the highlight gradient
if ([[self menuItem] isHighlighted]) {

    NSInteger tint = [[NSUserDefaults standardUserDefaults] integerForKey:@"AppleAquaColorVariant"];
    NSImage *image = (AppleAquaColorGraphite == tint) ? menuItemFillGray : menuItemFillBlue;

    NSDrawThreePartImage(dirtyRect, nil, image, nil, NO,
        NSCompositeSourceOver, 1.0, [self isFlipped]);
}
else if ([self backgroundColor]) {

    [[self backgroundColor] set];
    NSRectFill(dirtyRect);
}

РЕДАКТИРОВАТЬ

Должны были определить это:

enum AppleAquaColorVariant {
    AppleAquaColorBlue = 1,
    AppleAquaColorGraphite = 6,
};

Они соответствуютдва варианта внешнего вида в Системных настройках.Кроме того, menuItemFillGray и menuItemFillBlue - это просто NSImages стандартных градиентов заполнения пунктов меню.

1 голос
/ 22 мая 2019

Обновление на 2019 год:

class CustomMenuItemView: NSView {
    private var effectView: NSVisualEffectView

    override init(frame: NSRect) {
        effectView = NSVisualEffectView()
        effectView.state = .active
        effectView.material = .selection
        effectView.isEmphasized = true
        effectView.blendingMode = .behindWindow

        super.init(frame: frame)
        addSubview(effectView)
        effectView.frame = bounds
    }

    required init?(coder decoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func draw(_ dirtyRect: NSRect) {
        effectView.isHidden = !(enclosingMenuItem?.isHighlighted ?? false)
    }
}

Установите один из них на menuItem.view.

(Кредит принадлежит Сэму Соффсу, который помог мне выяснить это и прислал мне почти этот коддословно.)

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