开发者

How to programmatically open an NSComboBox's list?

I've been around this for a while.. I thought this should be an easy task, but it isn't =D

What I am trying t开发者_开发技巧o do, is to display the combobox's list when the user clicks the combobox but not specifically in the button.

Any Idea? Thanks in advance!


This answer fits the title of the question, but not question itself. Omer wanted to touch a text field and have the box popup.

This solution shows the popup when the user enters text.

I found this answer on cocoabuilder from Jens Alfke. I reposted his code here. Thanks Jens.

original cocoabuilder post: (http://www.cocoabuilder.com/archive/cocoa)

@interface NSComboBox (MYExpansionAPI)
@property (getter=isExpanded) BOOL expanded;
@end

@implementation NSComboBox (MYExpansionAPI)

- (BOOL) isExpanded
{
    id ax = NSAccessibilityUnignoredDescendant(self);
    return [[ax accessibilityAttributeValue:
                NSAccessibilityExpandedAttribute] boolValue];
}

- (void) setExpanded: (BOOL)expanded
{
    id ax = NSAccessibilityUnignoredDescendant(self);
    [ax accessibilitySetValue: [NSNumber numberWithBool: expanded]
                 forAttribute: NSAccessibilityExpandedAttribute];
}

I used this code in my controlTextDidChange: method.

- (void) controlTextDidChange:(NSNotification *) aNotification {
  NSTextField *textField = [aNotification object];
  NSString *value = [textField stringValue];
  NSComboBox *box = [self comboBox];
  if (value == nil || [value length] == 0) {
    if ([box isExpanded]) { [box setExpanded:NO]; }
  } else {
    if (![box isExpanded]) { [box setExpanded:YES]; }
  }
}


  1. Returns true if the NSComboBox's list is expanded

    comboBox.cell?.isAccessibilityExpanded() ?? false
    
  2. Open the NSComboBox's list

    comboBox.cell?.setAccessibilityExpanded(true)
    
  3. Close the NSComboBox's list

    comboBox.cell?.setAccessibilityExpanded(false)
    

Ref. jmoody’s answer.


You can use the following code line:

 [(NSComboBoxCell*)self.acomboBox.cell performSelector:@selector(popUp:)];


Put

comboBoxCell.performSelector(Selector("popUp:"))

Into

override func controlTextDidChange(obj: NSNotification) {}

is what I ended up with. Thanks @Ahmed Lotfy

Here's the full code, it works for me on OSX 10.11

override func controlTextDidChange(obj: NSNotification) {
        if let comboBoxCell = self.comboBox.cell as? NSComboBoxCell {
            comboBoxCell.performSelector(Selector("popUp:"))
        }
}


Thanks to jmoody and Jens Alfke mentioned above. Here is a SWIFT translation of the above solution.

import Cocoa

class CComboBoxEx: NSComboBox {

override func drawRect(dirtyRect: NSRect) {
    super.drawRect(dirtyRect)
        // Drawing code here.

       }

func isExpanded() -> Bool{

    if let ax:AnyObject? = NSAccessibilityUnignoredDescendant(self) {
        if ax!.accessibilityAttributeValue(NSAccessibilityExpandedAttribute) != nil {
            return true
        }
    }
    return false
}

func setExpanded (bExpanded:Bool) {

    if let ax:AnyObject? = NSAccessibilityUnignoredDescendant(self) {
       ax!.accessibilitySetValue(NSNumber(bool: bExpanded), forAttribute: NSAccessibilityExpandedAttribute)
    }

 }



}


NSComboBox was not designed to work this way. Because the user may want to edit the text in the control, they'll need to be able to click it without unexpectedly popping up the choices.

You would need to subclass NSComboBoxCell and change this behavior ... but then you'd have a standard-looking control that does not behave in a standard way. If you're determined to do this, take a look at the open source version of NSComboBoxCell. The interesting methods appear to be -popUpForComboBoxCell: and friends.


Based on the other answers I wrote this solution (tested with Xcode 10.2.1, Swift 5). It uses the same ideas but it's a little shorter.

// Put this extension for NSComboBox somewhere in your project

import Cocoa

public extension NSComboBox {

    var isExpanded: Bool{
        set {
            cell?.setAccessibilityExpanded(newValue)
        }
        get {
            return cell?.isAccessibilityExpanded() ?? false
        }
    }
}

// Set your corresponding NSViewController as NSComboBoxDelegate 
// in the storyboard and add this piece of code 
// to expand the combobox when the user types

class MyViewController: NSViewController, NSComboBoxDelegate {

    func controlTextDidChange(_ notification: Notification) {
        guard let comboBox = notification.object as? NSComboBox else { return }
        if comboBox.isExpanded == false {
            comboBox.isExpanded = true
        }
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜