对NSPopUpButton进行排序

时间:2012-06-19 09:32:36

标签: objective-c cocoa

我有一个需要在NSPopUpButton中显示的元素列表。我希望PopUp按钮按字母顺序排序显示列表。此外,列表中有一个新的MenuItem,它将从文本字段中拾取一个字符串并将其插入到PopUp按钮中。所以,我想问两个问题:

  1. 在NSPopUpButton中按排序顺序显示元素列表的正确方法是什么?
  2. 我应该如何处理向NSPopUpButton插入新元素以便维护排序顺序?

3 个答案:

答案 0 :(得分:2)

如果您使用NSArrayController填充弹出按钮(或更确切地说,它的菜单),那么您只需定义一个排序描述符来处理排序。

让阵列控制器第一次使用弹出按钮可能有点棘手,但如果将弹出按钮的内容绑定到阵列控制器的arrangedObjects然后绑定内容值到模型对象的合适字符串属性,你应该没问题。

然后,添加一个新项只需要通过数组控制器添加一个项目。

因此,如果您不熟悉NSArrayController类和绑定,以下是如何在Interface Builder中执行此操作的简短说明。假设您的元素具有名为name的字符串属性。

  1. 在您的nib文件的所有者(例如,应用委托)中创建一个(可变的)数组属性来保存您的元素。
  2. 在Interface Builder中创建一个数组控制器对象。
  3. 将其内容数组绑定到刚创建的数组属性。可以在Xcode的Bindings Inspector(Cmd-Opt-7)中设置绑定。
  4. 向窗口添加弹出按钮。
  5. 将弹出按钮的内容绑定设置为阵列控制器的arrangedObjects控制器键。这是该绑定的默认选项。
  6. 将弹出按钮的内容值绑定设置为数组控制器的arrangedObjects控制器密钥和name模型密钥路径。这将在菜单中显示正确的文字。
  7. 在代码的某处,创建一个排序描述符并在数组控制器上设置它(使用setSortDescriptors:方法)。为此,您可能希望在文件所有者上定义一个插座来保存阵列控制器。
  8. 要向弹出按钮添加新元素,请使用数组控制器的add:方法。
  9. 这应该可以让你使用最少的代码,以及一点点Interface Builder魔法。

    对于相当简单的UI元素,绑定可以真正节省大量工作。关于他们的更多信息here

    编辑添加示例:

    有关如何执行此操作的示例,请考虑具有应用程序委托的应用程序,该应用程序委托具有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];
    

答案 1 :(得分:1)

我设法使用以下绑定对弹出按钮进行排序:

[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添加到阵列控制器,之前添加的子菜单消失,如下图所示:

在添加新项目之前:
enter image description here


添加新商品后:
enter image description here


我们对元素进行排序时会显示相同的行为 关于解决这个问题的任何想法??

答案 2 :(得分:0)

感谢@Monolo的回答

我已经能够在NSArrayController的弹出窗口中加载值(已存储在NSMutableArray中)。但我仍然坚持排序的事情。下面是代码,我无法弄清楚它有什么问题 的 ControllerClass.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