Domanda

Ho un NSView personalizzato (è uno dei tanti e tutti vivono all'interno di un NSCollectionView - Non credo che sia rilevante, ma chi lo sa). Quando scatto la vista, voglio che cambiare il suo stato di selezione (e ridisegnare se stessa di conseguenza); quando si fa doppio clic la vista, voglio che per far comparire una finestra di anteprima più grande per l'oggetto che è stato appena fatto doppio clic.

Il mio primo si presentava così:

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

, che in gran parte ha funzionato benissimo. Tranne che, quando si fa doppio clic la vista, i cambiamenti di stato selezione e la finestra si apre. Questo non è esattamente quello che voglio.

E sembra che ci siano due opzioni. Posso o riportare lo stato di selezione per rispondere a un doppio clic (annullando l'errante un clic) o posso finagle qualche soluzione NSTimer per costruire un ritardo prima di rispondere al click. In altre parole, posso fare in modo che un secondo clic non è imminente prima di cambiare lo stato di selezione.

Questo sembrava più elegante, così è stato l'approccio che ho preso in un primo momento. L'unica vera guida che ho trovato da Google era su un sito senza nome con un trattino nel suo nome. Questo approccio funziona per lo più con un grande avvertimento.

La questione in sospeso è "Quanto tempo dovrebbe il mio NSTimer aspettare?". Il sito senza nome suggerisce di utilizzare la funzione di carbonio GetDblTime(). Oltre ad essere inutilizzabile in applicazioni a 64 bit, l'unica documentazione che posso trovare per esso dice che è il ritorno orologio-zecche. E io non so come convertire quelli in secondi per NSTimer.

Allora qual è il "corretto" risposta qui? Fumble in giro con GetDblTime()? "Annulla" la selezione su un doppio clic? Io non riesco a capire l'approccio di cacao-idiomatica.

È stato utile?

Soluzione

Ritardare il cambio dello stato di selezione è (da quello che ho visto) il modo consigliato di fare questo.

E 'abbastanza semplice da implementare:

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

(Si noti che nel 10.6, il doppio intervallo di scatto è accessibile come un metodo di classe su NSEvent)

Altri suggerimenti

Se le operazioni a singolo clic e doppio clic sono davvero separati e non collegati, è necessario utilizzare un timer sul primo clic e aspettare di vedere se un doppio clic sta per accadere. Questo è vero su qualsiasi piattaforma.

Ma che introduce un ritardo imbarazzante nelle vostre operazioni single-click che gli utenti in genere non piace. Quindi non si vede che l'approccio usato molto spesso.

Un approccio migliore è quello di avere il vostro singolo clic e le operazioni di fare doppio clic su essere connessi e complementari. Ad esempio, se si un solo clic su un'icona nel Finder è selezionata (immediatamente), e se si fa doppio clic su un'icona è selezionata e aperta (immediatamente). Questo è il comportamento che si dovrebbe puntare per.

In altre parole, le conseguenze di un singolo clic dovrebbe essere collegato al vostro comando doppio clic. In questo modo, si può trattare con gli effetti del singolo-click nel gestore doppio click senza dover ricorrere all'utilizzo di un timer.

Aggiungi due proprietà alla visualizzazione personalizzata.

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

@end

sovrascrivere il metodo mouseUp: nella visualizzazione personalizzata.

// 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];
        }
    }
}

Registra il controller come target con una 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;
}

Implementare cosa si dovrebbe fare quando un doppio click succede.

// CustomController.m
- (void)doubleClicked:(id)sender {
  // DO SOMETHING.
}

Personalmente, penso che è necessario chiedersi perché si desidera che questo comportamento non standard.

Si può puntare a qualsiasi altra applicazione che tratta il primo clic in un doppio clic come diverso da un singolo clic? Non riesco a pensare di qualsiasi ...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top