簡體   English   中英

NSPopupButton中的分隔項與綁定

[英]Separator item in NSPopupButton with bindings

NSPopupButton的內容綁定到NSArray字符串。

我們如何通過綁定插入分隔項?

- ”字符串(如舊版/經典日)不起作用,即字面上顯示為“ - ”菜單項。

有沒有標准的Cocoa類和綁定的開箱即用的解決方案?

這應該是一個微不足道的問題,但我找不到任何解決問題的方法,不涉及像子類化NSMenuNSPopupButton或其他非直觀的工作。

在使用綁定時,我找不到一種干凈的方法來動態地將分隔符添加到菜單中。 我發現最簡單(也是最可重用)的方法是使用NSMenuDelegate動態地將具有特定標題的NSMenuItems替換為@"---" ,並在menuNeedsUpdate: delegate方法中使用分隔符項。

步驟1:創建符合NSMenuDelegate協議的NSObject

#import <Cocoa/Cocoa.h>

@interface SeparatorMenuDelegate : NSObject <NSMenuDelegate>
@end
@implementation SeparatorMenuDelegate

-(void)menuNeedsUpdate:(NSMenu *)menu {
    NSArray* fakeSeparators = [[menu itemArray] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"title == '---'"]];
    for (NSMenuItem* fakeSep in fakeSeparators) {
        [menu insertItem:[NSMenuItem separatorItem] atIndex:[menu indexOfItem:fakeSep]];
        [menu removeItem:fakeSep];
    }
}

@end

第2步:在Interface Builder中鏈接。

將Object拖出到包含NSPopupButton實例的場景中。 拖出一個對象

將對象的類設置為SeparatorMenuDelegate

設置對象的類

旋轉打開文檔大綱中的NSPopupButton控件,然后選擇其中的菜單。 然后將Menu的委托設置為您之前拖動的SeparatorMenuDelegate對象。

設置菜單的委托

在此之后,菜單中標題為“”---“的所有項目都將轉換為分隔項目。

如果在同一場景中有多個NSPopupButton實例,則可以將其Menu的委托設置為同一對象(每個場景只需要一個SeparatorMenuDelegate )。

恕我直言,最干凈的解決方案仍然是子類化NSMenu - 這種定制正是子類化的目的。 以下解決方案基於@matt多年前在Cocoabuilder所寫的內容 ,並更新為更普遍適用,包括High Sierra。

首先 ,定義一個“魔術字符串”來表示代碼中的分隔符項; 在頭文件中執行此操作,所有受影響的類將導入。 在這個例子中,我選擇了“---”,但當然,這可以是你喜歡的任何字符串:

#define MY_MENU_SEPARATOR @"---"

,子類NSMenu並覆蓋添加菜單項的兩種方法,以便處理特殊的分隔符案例:

@implementation MyMenu

- (NSMenuItem*)addItemWithTitle:(NSString*)aString action:(SEL)aSelector keyEquivalent:(NSString*)keyEquiv
    {
        if ([aString isEqualToString:MY_MENU_SEPARATOR])
        {
            NSMenuItem *separator = [NSMenuItem separatorItem];
            [self addItem:separator];
            return separator;
        }
        return [super addItemWithTitle:aString action:aSelector keyEquivalent:keyEquiv];
    }


- (NSMenuItem*)insertItemWithTitle:(NSString*)aString action:(SEL)aSelector keyEquivalent:(NSString*)keyEquiv atIndex:(NSInteger)index
    {
        if ([aString isEqualToString:MY_MENU_SEPARATOR])
        {
            NSMenuItem *separator = [NSMenuItem separatorItem];
            [self insertItem:separator atIndex:index];
            return separator;
        }
        return [super insertItemWithTitle:aString action:aSelector keyEquivalent:keyEquiv atIndex:index];
    }   

@end

就是這樣。 Interface BuilderIdentity檢查中將受影響的菜單設置為MyMenu類,它們將在需要的位置插入分隔符項。 適用於菜單欄菜單和彈出窗口。

這是n.Drake在Swift 3.1中的答案:

class MySeparatorMenuDelegate : NSObject, NSMenuDelegate {
    func menuNeedsUpdate(_ menu: NSMenu) {
        for (ix,mi) in menu.items.enumerated() {
            if mi.title == "---" {
                menu.removeItem(at: ix)
                menu.insertItem(NSMenuItem.separator(), at: ix)
            }
        }
    }
}

請查看Mac OS X 10.5中添加的NSContentPlacementTagBindingOption的文檔。 在Interface Builder的Bindings檢查器中,這可用於彈出菜單按鈕等元素; 轉到“值選擇”部分,查看“內容放置標記”的任何內容類別(內容,內容對象,內容值)。 字段值應該是與某個菜單項的標簽號匹配的數字。

綁定數組的內容將插入菜單中,而不是具有指定標記值的項目。 在這種情況下,靜態菜單將包含您的分隔符項和至少一個其他項,以指定數組值的位置。

[[popupButton menu] addItem:[NSMenuItem separatorItem]];

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM