[英]Separator item in NSPopupButton with bindings
NSPopupButton
的內容綁定到NSArray
字符串。
我們如何通過綁定插入分隔項?
“ -
”字符串(如舊版/經典日)不起作用,即字面上顯示為“ -
”菜單項。
有沒有標准的Cocoa類和綁定的開箱即用的解決方案?
這應該是一個微不足道的問題,但我找不到任何解決問題的方法,不涉及像子類化NSMenu
, NSPopupButton
或其他非直觀的工作。
在使用綁定時,我找不到一種干凈的方法來動態地將分隔符添加到菜單中。 我發現最簡單(也是最可重用)的方法是使用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 Builder的Identity檢查器中將受影響的菜單設置為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.