2009-07-29 41 views
7

Tôi có một NSSegmentedControl trên giao diện người dùng của tôi với 4 nút. Việc kiểm soát được kết nối với một phương pháp mà sẽ gọi các phương thức khác nhau tùy thuộc vào phân khúc được nhấp:Hiển thị menu NSSegmentedControl khi phân đoạn được nhấp, mặc dù đã đặt hành động

- (IBAction)performActionFromClick:(id)sender { 
    NSInteger selectedSegment = [sender selectedSegment]; 
    NSInteger clickedSegmentTag = [[sender cell] tagForSegment:selectedSegment]; 

    switch (clickedSegmentTag) { 
      case 0: [self showNewEventWindow:nil]; break; 
      case 1: [self showNewTaskWindow:nil]; break; 
      case 2: [self toggleTaskSplitView:nil]; break; 
      case 3: [self showGearMenu]; break; 
    } 
} 

Segment 4 có có một thực đơn gắn liền với nó trong phương pháp awakeFromNib. Tôi muốn menu này thả xuống khi người dùng nhấp vào phân khúc. Tại thời điểm này, nó sẽ chỉ giảm nếu người dùng nhấp vào & giữ trên menu. Từ nghiên cứu trực tuyến của tôi, điều này là do hành động được kết nối.

Tôi hiện đang làm việc xung quanh bằng cách sử dụng một số mã để lấy điểm gốc của điều khiển phân đoạn và bật trình đơn ngữ cảnh bằng cách sử dụng NSMenu popUpContextMenu:withEvent:forView nhưng điều này khá dễ hiểu và có vẻ kém so với hành vi chuẩn của trình đơn thả xuống dưới ô điều khiển được phân đoạn.

Có cách nào tôi có thể có menu thả xuống vì nó nên sau một nhấp chuột duy nhất thay vì làm điều menu ngữ cảnh hacky?

+0

Trong 10.10.2/Xcode 6.3, hành vi tiêu chuẩn cho menu là thả xuống khi người dùng nhấp vào phân đoạn không có hành động nào được đính kèm; và yêu cầu nhấp và giữ khi phân đoạn có IBAction. Vì hành động của bạn là 'trình đơn hiển thị', bạn sẽ có thể xóa nó. –

+0

Bạn làm cách nào để đính kèm hành động vào từng phân đoạn? –

Trả lời

3

Tôi không chắc chắn về bất kỳ cách tích hợp nào để thực hiện việc này (mặc dù nó thực sự là một lỗ hổng rõ ràng trong API NSSegmentedControl).

Đề xuất của tôi là tiếp tục thực hiện những gì bạn đang thực hiện bật lên trình đơn ngữ cảnh. Tuy nhiên, thay vì chỉ sử dụng nguồn gốc sự kiểm soát phân đoạn, bạn có thể vị trí của nó trực thuộc phân khúc (như bạn muốn) bằng cách làm như sau:

NSPoint menuOrigin = [segmentedControl frame].origin; 
menuOrigin.x = NSMaxX([segmentedControl frame]) - [segmentedControl widthForSegment:4]; 
// Use menuOrigin where you _were_ just using [segmentedControl frame].origin 

Nó không phải hoàn hảo hay lý tưởng, nhưng nó phải được công việc làm và cung cấp cho giao diện/hành vi mà người dùng của bạn mong đợi.

(như là một sang một bên, NSSegmentedControl thực sự cần có một phương pháp -rectForSegment:)

+1

Đồng ý rằng nó khá lame không có được xây dựng trong cách để làm điều này. Tôi đã nộp nó lên Radar. Dupe: http://openradar.appspot.com/radar?id=61419 –

2

widthForSegment: trả về số không nếu phân khúc tự động kích cỡ. Nếu bạn không quan tâm đến các API không có giấy tờ, có một rectForSegment:

  • (NSRect) rectForSegment: (NSInteger) phân khúc inFrame: (NSRect) khung;

Nhưng để trả lời câu hỏi ban đầu, một cách dễ dàng hơn để có được menu để bật lên ngay lập tức là để phân lớp NSSegmentedCell và trở về 0 cho (một lần nữa, không có giấy tờ)

  • (kép) _menuDelayTimeForSegment: (NSInteger) phân đoạn;
14

Phân lớp NSSegmentedCell, phương pháp ghi đè bên dưới và thay thế lớp ô trong IB. (Không yêu cầu API riêng tư).

- (SEL)action 
{ 
    //this allows connected menu to popup instantly (because no action is returned for menu button) 
    if ([self tagForSegment:[self selectedSegment]]==0) { 
     return nil; 
    } else { 
     return [super action]; 
    } 
} 
+1

Công trình này tuyệt vời. Đến nay giải pháp sạch nhất mà tôi đã thấy. Cảm ơn! – djeckhart

+2

Giải pháp tốt, thực sự. Một gợi ý nhỏ: đặt điều kiện if thành '[self menuForSegment: [self selectedSegment]]! = Nil'; theo cách đó bạn không phải đặt thẻ. –

+1

Phân loại này hoạt động tốt. Nếu phân đoạn chưa được chọn, việc nhấp vào phân khúc đó không có gì. Nhấp chuột sau khi phân đoạn được chọn sau đó tạo trình đơn. Tôi không thể thấy cách này hoạt động cho các bạn mà không điều chỉnh hành vi đó. –

3

Đây là phiên bản Swift của câu trả lời của J Hoover và bản mod của Adam Treble. Ghi đè không trực quan như tôi nghĩ, vì vậy điều này hy vọng sẽ giúp người khác.

override var action : Selector { 
     get { 
      if self.menuForSegment(self.selectedSegment) != nil { 
       return nil 
      } 
      return super.action 
     } 
     set { 
      super.action = newValue 
     } 
    } 
+0

Tôi đã làm điều này, nhưng vì lý do nào đó, phương thức 'get' không bao giờ được gọi. –

Các vấn đề liên quan