对菜单中显示归属字符串时,它的突然出现,我建议包含弹出电池有它的Content
绑定指向表列设置为本身必然的NSAttributedStrings
的NSArray
包含所有选项的NSArrayController
,然后将通过弹出电池包含在NSMenu
委托,然后做这样的事情在委托:
- (void)menuNeedsUpdate:(NSMenu*)menu
{
for (NSMenuItem* item in menu.itemArray)
if ([item.representedObject isKindOfClass: [NSAttributedString class]])
{
item.attributedTitle = item.representedObject;
}
}
会已经把未调戏NSAttributedString
到的该representedObject
属性的结合NSMenuItem
。你可以在那里找到它,并把它放到attributedTitle
属性中,这将使它显示菜单中的属性字符串。总而言之,在菜单中绘制的一个菜单项,它的attributedTitle
属性被适当地设置,将绘制样式文本。
稍微复杂一点的是,当菜单是而不是弹出时,使属性字符串在弹出单元中按预期绘制。 NSPopUpButtonCell
似乎通过有一个NSMenuItem
绘制它呈现。不幸的是,创建该特定的NSMenuItem
似乎并未包含将未调用的值加入其中。相反,标题似乎是以简单的,非属性的字符串形式发送的。我已经无法设计出这种优雅的解决方案,但我没有想出了一个不雅的解决办法:
首先添加NSTextField
列到你的NSTableView
是正确绘制当前选择的属性串(即带属性)。隐藏该列。子类NSPopUpButtonCell
或使用类别和关联存储向NSPopUpButtonCell
添加新的私有资产。该属性将包含一个块,您可以在绘制时使用该块从隐藏列中获取相应的单元格。添加一个NSTableViewDelegate
,并执行-tableView:dataCellForTableColumn:row:
。当它被调用弹出列时,创建块以从隐藏列中获取单元格并将其推入到子类的属性中。然后在绘制时间,如果你有一个单元格获取块,清除它通常用于渲染的title
,通常用于渲染,调用super(获取弹出的小箭头),然后获取替代单元格,以及它也画了。下面的代码是什么样子:
@interface AppDelegate : NSObject <NSApplicationDelegate, NSMenuDelegate, NSTableViewDelegate>
@property (assign) IBOutlet NSTableColumn *popUpColumn;
@property (assign) IBOutlet NSTableColumn *surrogateColumn;
// ...snip...
@end
@interface SOPopUpButtonCell : NSPopUpButtonCell
typedef NSTextFieldCell* (^CellFetcher)();
@property (nonatomic, copy, readwrite) CellFetcher cellFetcherBlock;
@end
@implementation AppDelegate
// ...snip...
- (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
if (nil == tableColumn || self.popUpColumn != tableColumn)
return nil;
SOPopUpButtonCell* defaultCell = (SOPopUpButtonCell*)[tableColumn dataCellForRow: row];
const NSUInteger columnIndex = [[tableView tableColumns] indexOfObject: self.surrogateColumn];
CellFetcher f = ^{
return (NSTextFieldCell*)[tableView preparedCellAtColumn: columnIndex row: row];
};
defaultCell.cellFetcherBlock = f;
return defaultCell;
}
@end
@implementation SOPopUpButtonCell
- (void)setCellFetcherBlock:(CellFetcher)cellFetcherBlock
{
if (_cellFetcherBlock != cellFetcherBlock)
{
if (_cellFetcherBlock)
Block_release(_cellFetcherBlock);
_cellFetcherBlock = cellFetcherBlock ? Block_copy(cellFetcherBlock) : nil;
}
}
- (void)dealloc
{
if (_cellFetcherBlock)
Block_release(_cellFetcherBlock);
[super dealloc];
}
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
CellFetcher f = self.cellFetcherBlock;
if (f)
self.menuItem.title = @"";
[super drawWithFrame:cellFrame inView:controlView];
if (f)
NSTextFieldCell* surrogateCell = f();
[surrogateCell drawWithFrame: cellFrame inView: controlView];
}
@end
我必须承认,这让我觉得有点脏,但它似乎把工作做好。我已经发布的所有代码,包括在GitHub上所有相关的绑定在厦门国际银行: Example Project
希望有所帮助。
感谢您的解决方案!我遇到了同样的问题,即'NSPopUpButtonCell'无法正确更新自己,所以在花费了几个小时并尝试各种方法之后,我继续通过tableView:dataCellForTableColumn:row:从表视图委托中填充弹出式按钮,然后只是绑定弹出窗口的选定索引属性.. – Jay