19

私には習慣がありますNSView(それは多くの習慣の1つであり、それらはすべて内部に住んでNSCollectionViewいます—それは関係ないと思いますが、誰にもわかりません)。ビューをクリックすると、選択状態が変更されます (それに応じて再描画されます)。ビューをダブルクリックすると、ダブルクリックしたオブジェクトの大きなプレビュー ウィンドウがポップアップ表示されるようにします。

私の最初は次のように見えました:

- (void)mouseUp: (NSEvent *)theEvent {
    if ([theEvent clickCount] == 1) [model setIsSelected: ![model isSelected]];
    else if ([theEvent clickCount] == 2) if ([model hasBeenDownloaded]) [mainWindowController showPreviewWindowForPicture:model];
}

これはほとんどうまくいきました。ただし、ビューをダブルクリックすると、選択状態が変わりウィンドウがポップアップします。これはまさに私が望むものではありません。

2つのオプションがあるようです。NSTimerダブルクリックに応答するときに選択状態を元に戻す (誤ったシングルクリックを元に戻す) か、シングル クリックに応答する前に遅延を組み込む何らかの解決策を練ることができます。つまり、選択状態を変更する前に、2 回目のクリックが行われないことを確認できます。

これはよりエレガントに思えたので、私が最初に取ったアプローチでした。私が Google から見つけた唯一の実際のガイダンスは、名前にハイフンが含まれる名前のないサイトに関するものでした。このアプローチは、ほとんどの場合、1 つの大きな注意点があります。

未解決の質問は、「どのくらいNSTimer待つ必要がありますか?」です。名前のないサイトでは、Carbon 関数の使用が提案されていますGetDblTime()。64 ビット アプリでは使用できないことを除けば、私が見つけた唯一のドキュメントには、クロック ティックを返すと書かれています。そして、それらを秒に変換する方法がわかりませんNSTimer

では、ここでの「正しい」答えは何ですか? GetDblTime()?をいじります。ダブルクリックで選択を「元に戻す」? ココアの慣用的なアプローチがわかりません。

4

5 に答える 5

42

選択状態の変更を遅らせることは、(私が見てきたことから)これを行うための推奨される方法です。

実装は非常に簡単です。

- (void)mouseUp:(NSEvent *)theEvent
{
    if([theEvent clickCount] == 1) {
        [model performSelector:@selector(toggleSelectedState) afterDelay:[NSEvent doubleClickInterval]];
    }
    else if([theEvent clickCount] == 2)
    {
        if([model hasBeenDownloaded])
        {
                [NSRunLoop cancelPreviousPerformRequestsWithTarget: model]; 
                [mainWindowController showPreviewWindowForPicture:model];
        }
    }
}

(10.6 では、ダブルクリック間隔は のクラス メソッドとしてアクセスできることに注意してくださいNSEvent)

于 2009-11-03T05:24:18.703 に答える
8

シングルクリックとダブルクリックの操作がまったく別のものであり、無関係である場合は、最初のクリックでタイマーを使用し、ダブルクリックが発生するかどうかを確認する必要があります。これは、どのプラットフォームでも同じです。

しかし、これにより、ユーザーが通常好まないシングルクリック操作に厄介な遅延が発生します。したがって、そのアプローチが頻繁に使用されることはありません。

より良いアプローチは、シングルクリック操作とダブルクリック操作を関連付けて補完することです。たとえば、Finder でアイコンをシングルクリックすると (すぐに) そのアイコンが選択され、アイコンをダブルクリックすると (すぐに) 選択されて開かれます。それが目指すべき行動です。

つまり、シングルクリックの結果は、ダブルクリック コマンドに関連している必要があります。そうすれば、タイマーを使用しなくても、ダブルクリック ハンドラーでシングルクリックの効果を処理できます。

于 2009-11-03T17:40:23.130 に答える
2

カスタムビューに2つのプロパティを追加します。

// CustomView.h
@interface CustomView : NSView {
  @protected
    id      m_target;
    SEL     m_doubleAction;
}
@property (readwrite) id target;
@property (readwrite) SEL doubleAction;

@end

mouseUp:カスタムビューでメソッドを上書きします。

// CustomView.m
#pragma mark - MouseEvents

- (void)mouseUp:(NSEvent*)event {
    if (event.clickCount == 2) {
        if (m_target && m_doubleAction && [m_target respondsToSelector:m_doubleAction]) {
            [m_target performSelector:m_doubleAction];
        }
    }
}

コントローラをでとして登録しtargetますdoubleAction

// CustomController.m
- (id)init {
    self = [super init];
    if (self) {
        // Register self for double click events.
        [(CustomView*)m_myView setTarget:self];
        [(CustomView*)m_myView setDoubleAction:@selector(doubleClicked:)];
    }
    return self;
}

ダブルクリックが発生したときに実行する必要があることを実装します。

// CustomController.m
- (void)doubleClicked:(id)sender {
  // DO SOMETHING.
}
于 2011-12-19T17:12:48.640 に答える
2

個人的には、なぜこの非標準的な動作が必要なのかを自問する必要があると思います。

ダブルクリックの最初のクリックをシングルクリックとは異なるものとして扱う他のアプリケーションを指摘できますか? 何も思いつかない...

于 2009-11-03T05:26:15.550 に答える