2012-03-23 14 views
5

ビューベースNSTableViewがあります。表の各ビューにはカスタムテキストフィールドがあります。mouseDown:NSTableView内のカスタムNSTextFieldに

ユーザーがテーブルのビュー内でテキストフィールド(ラベル)をクリックしたときにアクションを起こしたいと思います(各テーブルセルでカスタムアクションを持つハイパーリンクがあるとします)。

マウスイベントを捕捉するためのサブクラスNSTextFieldを作成しました。ただし、最初のクリックではなく、2回目のクリックでのみ発生します。

私はNSButtonを使ってみましたが、すぐに発火しました。ここで

は、カスタムラベルのためのコードです:

@implementation HyperlinkTextField 

- (void)mouseDown:(NSEvent *)theEvent { 
    NSLog(@"link mouse down"); 
} 

- (void)mouseUp:(NSEvent *)theEvent { 
    NSLog(@"link mouse up"); 
} 

- (BOOL)acceptsFirstResponder { 
    return YES; 
} 

- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent { 
    return YES; 
} 
@end 

答えて

6

それはNSTableViewNSOultineViewが異なっNSButtonよりもNSTextFieldインスタンスのファーストレスポンダの状態を扱うことが判明しました。

ボタンのような最初のクリックに応答するラベルを取得するキーは、私のカスタムテキストフィールドクラスの場合にはYESを返すように[NSResponder validateProposedFirstResponder:forEvent:]を上書きすることです。

ドキュメント:

http://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSResponder_Class/Reference/Reference.html#//apple_ref/occ/instm/NSResponder/validateProposedFirstResponder:forEvent

1

テーブルビューは、それがあるべき最初の応答者、であるか、あなたがクリックしたときに、行が変更されませんので、あなたが見ている動作ですラベル上で - これは、ユーザーがテーブル行をクリックするときに期待する動作です。ラベルをサブクラス化するのではなく、テーブルビューをサブクラス化してmouseDownをオーバーライドする方が良いと思います。スーパーのmouseDown:の実装を呼び出した後、ヒットテストを実行して、ユーザーがラベルをクリックしたことを確認できます。

@implementation CustomTable 

- (void)mouseDown:(NSEvent *)theEvent 
{ 
    [super mouseDown:theEvent]; 
    NSPoint point = [self convertPoint:theEvent.locationInWindow fromView:nil]; 
    NSView *theView = [self hitTest:point]; 
    if ([theView isKindOfClass:[NSTextField class]]) 
    { 
     NSLog(@"%@",[(NSTextField *)theView stringValue]); 
    } 
} 

@end 
+0

ありがとう、私はそれを試みます。 1つの質問:最初のクリックはNSButtonで動作します(テーブル行はその場合選択されません)。その動作をエミュレートする方法はありますか? – Mark

+0

おそらくありますが、わかりません。私はacceptsFirstMouseおよび/またはacceptsFirstResponderに対してYESを返すとそのことが行われていると思います。 – rdelmar

+0

ボタンを使用した場合の動作を確認するには、ボタンを使用するだけではいかがですか?あなたは境界線をオフにすることができ、とにかく境界線のないラベルのように見えます。境界線が必要な場合は、境界線のないボタンをNSBoxに埋め込むことができます。 – rdelmar

7

は同じ問題を抱えていました。ここで受け入れられた答えは私にとってはうまくいかなかった。多くの苦労の末、デフォルトの "Regular"に対して "None"を選択し、IBのテーブルビューの "Highlight"オプションの "Source List"を他のオプションとすると、魔法のように機能しました!

編集:回答が示唆するように、テキストフィールドではなく、テーブルビューでメソッドがオーバーロードされるため、受け入れられた回答が誤解を招くことが判明しました。 https://stackoverflow.com/a/13579469/804616でより明確に示されていますが、いずれにしても、より具体的であると少しハッキリします。

+0

これは動作しません。たぶんあなたは何か他のことをしました –

+2

これは実際に動作するようです。私はmouseUpをトリガしようとしていましたが、どちらの方法でも動作しません。 MouseDownは両方とも機能します –

+0

これは動作しますが、テーブルビューでソースリストテーブルの表示スタイルを使用する場合はどうなりますか? –

1

まったく同じ状況では、transparenttrue/YESに設定してNSButtonを埋め込むことができました。

class LinkButton: NSTextField { 

    var clickableButton:NSButton? 

    override func viewDidMoveToSuperview() {    
     let button = NSButton() 
     self.addSubview(button) 

     //setting constraints to cover the whole textfield area (I'm making use of SnapKit here, you should add the constraints your way or use frames 
     button.snp_makeConstraints { (make) -> Void in 
      make.edges.equalTo(NSEdgeInsetsZero) 
     } 
     button.target = self 
     button.action = Selector("pressed:") 
     button.transparent = true 
    } 

    func pressed(sender:AnyObject) { 
     print("pressed") 
    } 
0

テキストフィールドの編集を開始するには、window.makeFirstResponser(myTextfield)を使用します。オーバーライドmouseDown(withEvent TheEvent:NSEvent)メソッドからこのメッセージを送信します。