我有一个需要在 NSPopUpButton 中显示的元素列表。我希望 PopUp 按钮按字母顺序显示列表。此外,列表中有一个 NEW MenuItem,它将从文本字段中提取一个字符串并将其插入到 PopUp 按钮中。所以,有两个问题我想问:
- 在 NSPopUpButton 中按排序顺序显示元素列表的正确方法是什么?
- 我应该如何处理向 NSPopUpButton 插入新元素以保持排序顺序?
我有一个需要在 NSPopUpButton 中显示的元素列表。我希望 PopUp 按钮按字母顺序显示列表。此外,列表中有一个 NEW MenuItem,它将从文本字段中提取一个字符串并将其插入到 PopUp 按钮中。所以,有两个问题我想问:
如果您使用 anNSArrayController
来填充弹出按钮(或者更确切地说,它的菜单),那么您可以定义一个排序描述符来处理排序。
第一次让数组控制器与弹出按钮一起工作可能有点棘手,但如果您将弹出按钮的内容绑定到数组控制器的内容arrangedObjects
,然后将内容值绑定到模型对象的合适字符串属性,您应该美好的。
然后,添加一个新项目只需通过数组控制器添加一个项目。
因此,如果您不熟悉NSArrayController
类和绑定,以下是如何在 Interface Builder 中进行的简短描述。假设您的元素有一个名为name
.
arrangedObjects
控制器键。这是该绑定的默认选项。arrangedObjects
控制器键和name
模型键路径。这将在菜单中提供正确的文本。setSortDescriptors:
方法)。为此,您可能希望在文件所有者上定义一个出口来保存阵列控制器。add:
方法。这应该让您使用最少的自己的代码,以及一点 Interface Builder 的魔力。
对于相当简单的 UI 元素,绑定确实可以节省很多工作。更多关于他们在这里。
编辑添加一个例子:
有关如何完成此操作的示例,请考虑具有应用程序委托的应用程序,该应用程序具有data
属性、字典数组和name
属性。请注意,这是比您的示例更深的抽象级别,其中数组仅包含单个字符串。就个人而言,我更喜欢这种方式。
self.data = [NSMutableArray arrayWithObjects:
[NSDictionary dictionaryWithObjectsAndKeys:@"Flowers", @"name", nil],
[NSDictionary dictionaryWithObjectsAndKeys:@"Animals", @"name", nil],
[NSDictionary dictionaryWithObjectsAndKeys:@"Trees", @"name", nil],
nil];
// Sort the array controller alphabetically by the name property
NSSortDescriptor *sd = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
self.arrayController.sortDescriptors = [NSArray arrayWithObject:sd];
我已经设法使用以下绑定对弹出按钮进行排序:
[arrayController bind:@"contentArray" toObject:self withKeyPath:@"displayElements" options:nil];
[popUpButton bind:@"content" toObject:arrayController withKeyPath:@"arrangedObjects" options:nil];
[popUpButton bind:@"contentValues" toObject:arrayController withKeyPath:@"arrangedObjects.title" options:nil];
我还更改了 init 中的语句:
displayElements = [[NSMutableArray alloc] initWithObjects:@"one",@"two",@"three", nil];
至
displayElements = [[NSMutableArray alloc] initWithObjects:[[NSMenuItem alloc]initWithTitle:@"one" action:nil keyEquivalent:@""],
[[NSMenuItem alloc]initWithTitle:@"two" action:nil keyEquivalent:@""],
[[NSMenuItem alloc]initWithTitle:@"three" action:nil keyEquivalent:@""],
nil];
并且排序工作得很好。
现在的问题是,如果我将子菜单添加到任何菜单项,然后我将新的 NSMenuItem 添加到数组控制器,则先前添加的子菜单会消失,如下图所示:
添加新项之前:
添加新项目后:
当我们对元素进行排序时,会显示相同的行为。
有关解决此问题的任何想法?
感谢@Monolo 的回答
我已经能够在 NSArrayController 的弹出窗口中加载值(已存储在 NSMutableArray 中)。但我仍然坚持排序的事情。下面是代码,我无法弄清楚它有什么问题。
控制器类.h
@interface ControllerClass : NSObject{
NSWindow *window;
NSArray *sortDescriptorArray;
NSMutableArray *displayElements;
NSSortDescriptor *sortDescriptor;
IBOutlet NSArrayController *arrayController;
IBOutlet NSTextField *newItemTextField;
}
@property (readwrite,retain) NSMutableArray *displayElements;
-(id)init;
-(IBAction)AddItem:(id)sender;
@end
==================================================== ==========
ControllerClass.m
#import "ControllerClass.h"
@implementation ControllerClass
@synthesize displayElements;
-(id)init
{
self =[super init];
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"displayElements" ascending:YES];
sortDescriptorArray = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[arrayController setSortDescriptors:sortDescriptorArray];
displayElements = [[NSMutableArray alloc] initWithObjects:@"one",@"two",@"three", nil];
return self;
}
-(IBAction)AddItem:(id)sender
{
[arrayController addObject:[newItemTextField stringValue]];
}
@end