2009-07-29 9 views
7

私は4つのボタンでUIにNSSegmentedControlを持っています。コントロールがクリックされたセグメントに応じて異なるメソッドをコールするメソッドに接続されている:アクションが設定されているにもかかわらず、セグメントがクリックされたときにNSSegmentedControlメニューを表示

- (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; 
    } 
} 

セグメント4はawakeFromNib方法でそれに取り付けられたメニューを有しています。ユーザーがセグメントをクリックすると、このメニューがドロップダウンされます。この時点で、ユーザーが&をクリックするとメニューが停止します。オンラインで私の研究から、これは接続されたアクションのためです。

私は現在、セグメントコントロールの原点を取得し、NSMenuのpopUpContextMenu:withEvent:forViewを使用してコンテキストメニューをポップアップさせるためにいくつかのコードを使用していますが、これはかなりhacktasticで、メニューを持つ標準的な動作セグメント化されたコントロールセルの下にドロップダウンします。

ハッキーなコンテキストメニューを行うのではなく、シングルクリック後にメニューをドロップダウンする方法はありますか?

+0

10.10.2/Xcode 6.3で、メニューが表示されるのは、アクションが割り当てられていないセグメントをユーザーがクリックするとドロップダウンすることです。セグメントにIBActionがあるときにクリックアンドホールドを要求することができます。あなたの行動は「ショーメニュー」なので、あなたはそれを取り除くことができるはずです。 –

+0

個々のセグメントにアクションをどのように添付しますか? –

答えて

3

これを行うための組み込み方法はわかりません(実際はNSSegmentedControl APIには目立つ穴ですが)。

私がお勧めするのは、コンテキストメニューがポップアップしていることをやり続けることです。しかし、(あなたが望むように)、だけではなく、セグメント化されたコントロールの原点を使用するには、次の操作を実行して、セグメントの下にそれを直接配置することができます:

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

これは完璧なまたは理想的ではないのですが、それは仕事を得る必要があり、ユーザーが期待する外観/行動を与えます。

(さておき、NSSegmentedControl が本当に-rectForSegment:方法を必要として)

+1

これはかなり不自由なことに、組み込みの方法はありません。私はそれをレーダーに提出した。 Dupe away:http://openradar.appspot.com/radar?id=61419 –

2

widthForSegment:セグメント自動サイズ場合戻るゼロ。あなたが文書化されていないAPIを懸念していない場合は、rectForSegmentがあります:

  • (NSRect)rectForSegment:(NSInteger)セグメント インフレーム:(NSRect)フレーム。

しかし、メニューがすぐにポップアップ表示するために取得する簡単な方法は、NSSegmentedCellをサブクラス化し、(文書化されていない、再び)は0を返すことです、元の質問に答えるために

  • (ダブル)_menuDelayTimeForSegment:(NSInteger )セグメント;
14

サブクラスNSSegmentedCellは、以下のメソッドをオーバーライドし、IBのセルクラスを置き換えます。 (プライベートAPIは必要ありません)。

- (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

これはうまくいきます。はるかに私が見た最もクリーンなソリューションです。ありがとう! – djeckhart

+2

確かに良い解決策。 1つのマイナーな提案:if条件を '[self menusForSegment:[self selectedSegment]]!= nil'に設定します。タグを設定する必要はありません。 –

+1

このソーシャルは素晴らしいです。セグメントがまだ選択されていない場合は、そのセグメントをクリックしても何も行われません。セグメントが選択された後をクリックしてメニューを生成します。私はあなたのために、この動作を調整することなく、どのように動作するのか分かりません。 –

3

これは、J Hooverによる回答とAdam Trebleによる修正のスウィフトバージョンです。オーバーライドは私が思ったほど直感的ではなかったので、これはうまくいけば他の誰かを助けるでしょう。

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

私はこれをしましたが、何らかの理由で 'get'メソッドが呼び出されることはありません。 –

関連する問題