NSTableView 允许用户选择要显示的列
Posted
技术标签:
【中文标题】NSTableView 允许用户选择要显示的列【英文标题】:NSTableView to allow user to choose which columns to display 【发布时间】:2012-11-13 06:51:16 【问题描述】:任何人都知道如何允许用户通过右键单击然后选择来选择要显示的 NSTableView 的哪些列?就像 iTunes 一样。
【问题讨论】:
【参考方案1】:我已经实现了这个,以下应该可以在没有任何子类的情况下使用。
首先在 IB 中实现一个空菜单,并连接到 Table Header View 的菜单输出。
此方法(从 awakeFromNib 调用)从标题构造菜单的内容(并包括一个防止用户隐藏主列的测试)
- (void)initViewHeaderMenu:(id)view
//create our contextual menu
NSMenu *menu = [[view headerView] menu];
//loop through columns, creating a menu item for each
for (NSTableColumn *col in [view tableColumns])
if ([[col identifier] isEqualToString:COLUMNID_NAME])
continue; // Cannot hide name column
NSMenuItem *mi = [[NSMenuItem alloc] initWithTitle:[col.headerCell stringValue]
action:@selector(toggleColumn:) keyEquivalent:@""];
mi.target = self;
mi.representedObject = col;
[menu addItem:mi];
return;
这会调用以下内容来执行实际的隐藏/取消隐藏
- (void)toggleColumn:(id)sender
NSTableColumn *col = [sender representedObject];
[col setHidden:![col isHidden]];
您还需要设置 Menu 的委托并实现以下设置状态:-
#pragma mark NSMenu Delegate Methods
-(void)menuWillOpen:(NSMenu *)menu
for (NSMenuItem *mi in menu.itemArray)
NSTableColumn *col = [mi representedObject];
[mi setState:col.isHidden ? NSOffState : NSOnState];
【讨论】:
menuWillOpen
在此方法期间不要修改...菜单项。 也许menuNeedsUpdate
是更好的候选者?
如果方法名不是初始值设定项,则不应以“init”开头。
这太棒了。您可能希望添加mi.state = (col.isHidden ? NSOffState: NSOnState);
以在可见列旁边显示一个复选框。这需要在隐藏toggleColumn:
中的列后更新,就像 `[sender setState: (col.isHidden ? NSOffState: NSOnState)];【参考方案2】:
我基于 this blog post 扩展了 Milliways 的出色答案,并添加了以下功能:
显示可见列的复选标记 使用NSUserDefaults
保持设置
初始设置:
// Your intial Startup code
[self setupHeaderMenu:self.yourTableView];
创建菜单:
重要提示:由于 col.identifier
,您必须为 IB 中的每个表视图列设置一个“标识标识符”才能使其工作。
#pragma mark - Show Hide Columns
- (void)setupHeaderMenu:(NSTableView *)tableView
NSDictionary *savedCols = [[NSUserDefaults standardUserDefaults] dictionaryForKey:kUserDefaultsKeyVisisbleColumns];
NSMenu *menu = [NSMenu new];
for (NSTableColumn *col in tableView.tableColumns)
NSMenuItem *mi = [[NSMenuItem alloc] initWithTitle:[col.headerCell stringValue]
action:@selector(toggleColumn:)
keyEquivalent:@""];
mi.target = self;
if(savedCols)
BOOL isVisible = [savedCols[col.identifier] boolValue];
[col setHidden:!isVisible];
mi.state = (col.isHidden ? NSOffState: NSOnState);
mi.representedObject = col;
[menu addItem:mi];
tableView.headerView.menu = menu;
return;
切换方法
toggle方法将新配置保存在NSUserDefaults
- (void)toggleColumn:(NSMenuItem *)menu
NSTableColumn *col = menu.representedObject;
BOOL shouldHide = !col.isHidden;
[col setHidden:shouldHide];
menu.state = (col.isHidden ? NSOffState: NSOnState);
NSMutableDictionary *cols = @.mutableCopy;
for( NSTableColumn *column in self.yourTableView.tableColumns)
cols[column.identifier] = @(!column.isHidden);
[[NSUserDefaults standardUserDefaults] setObject:cols forKey:kUserDefaultsKeyVisibleColumns];
if(shouldHide)
[self.yourTableView sizeLastColumnToFit];
else
[self.yourTableView sizeToFit];
菜单委托
-(void)menuWillOpen:(NSMenu *)menu
for (NSMenuItem *mi in menu.itemArray)
NSTableColumn *col = [mi representedObject];
[mi setState:col.isHidden ? NSOffState : NSOnState];
结果
所以现在您可以选中/取消选中每一列,即使重新启动您的应用程序,配置也会保存。
【讨论】:
隐藏列有效,但如果您希望所有列的宽度均匀,它会失败。我在我的 tableview 上使用“uniform”,在我的列上使用“resize with tableview”。取消选中/检查一些后,宽度变得不均匀。知道如何解决这个问题吗? 太棒了!这很好用!我唯一需要添加的是隐藏/显示列的默认值,它可以使用了。谢谢!【参考方案3】:您需要将NSMenu
附加到具有NSMenuItems
列的表的标题并在右键单击时将其弹出。我通过继承NSViewController
并在其中附加我的表格视图来完成此操作。该类也应该是NSMenuDelegate
。下面的例子。
.h 文件:
@interface UserManagedColumnsTableViewController : NSViewController <NSMenuDelegate>
@property (weak) IBOutlet NSTableView *tableView;
@end
.m 文件:
@interface UserManagedColumnsTableViewController ()
- (void)toggleColumn:(id)sender;
@end
@implementation UserManagedColumnsTableViewController
- (void)awakeFromNib
[super awakeFromNib];
NSMenu *columnsMenu = [[NSMenu alloc] initWithTitle:@""];
for (NSTableColumn *column in self.tableView.tableColumns)
NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:[column.headerCell stringValue]
action:@selector(toggleColumn:)
keyEquivalent:@""];
menuItem.target = self;
menuItem.representedObject = column;
[columnsMenu addItem:menuItem];
columnsMenu.delegate = self;
[self.tableView.headerView setMenu:columnsMenu];
#pragma mark - NSMenuDelegate conformance
- (void)menuWillOpen:(NSMenu *)menu
for (NSMenuItem *menuItem in menu.itemArray)
NSTableColumn *column = [menuItem representedObject];
[menuItem setState:column.isHidden ? NSOffState : NSOnState];
#pragma mark - Private Methods
- (void)toggleColumn:(id)sender
NSTableColumn *column = [sender representedObject];
[column setHidden:![column isHidden]];
@end
【讨论】:
以上是关于NSTableView 允许用户选择要显示的列的主要内容,如果未能解决你的问题,请参考以下文章