2012-03-23 3 views
5

Ho un NSTableView basato su visualizzazione. Ogni vista nella tabella ha un campo di testo personalizzato.mouseDown: in un NSTextField personalizzato all'interno di NSTableView

Vorrei attivare un'azione quando l'utente fa clic sul campo di testo (etichetta) all'interno della vista della tabella (immagina di avere un collegamento ipertestuale con un'azione personalizzata in ogni cella di tabella).

Ho creato una sottoclasse di base NSTextField per catturare gli eventi del mouse. Tuttavia, attivano solo il secondo clic, non il primo clic.

Ho provato a utilizzare un NSButton e questo si accende subito.

Ecco il codice per l'etichetta personalizzata:

@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 

risposta

6

Si è scoperto che NSTableView e NSOultineView di gestire il primo stato del risponditore per NSTextField le istanze in modo diverso rispetto a un NSButton.

La chiave per far sì che l'etichetta risponda al primo clic come un pulsante è sovrascrivere [NSResponder validateProposedFirstResponder:forEvent:] per restituire YES in caso di classe di campo di testo personalizzata.

Documentazione:

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

1

Il comportamento che si sta vedendo è perché la vista tabella è il primo soccorritore, che dovrebbe essere o la riga non cambia quando si fa clic sull'etichetta - questo è il comportamento che un utente si aspetta facendo clic su una riga della tabella. Invece di sottoclassi l'etichetta, penso che sarebbe meglio sottoclasse la vista tabella e sovrascrivi mouseDown: lì. Dopo aver chiamato l'implementazione super di mouseDown :, puoi eseguire un hit test per verificare che l'utente abbia fatto clic sull'etichetta.

@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

Grazie, ci proverò. Una domanda: il primo clic funziona con un NSButton (la riga della tabella non è selezionata in quel caso). C'è un modo per emulare tale comportamento? – Mark

+0

Probabilmente esiste, ma non lo so. Avrei pensato che restituire SÌ per acceptFirstMouse e/o acceptFirstResponder lo avrebbe fatto. – rdelmar

+0

Se vuoi il comportamento che ottieni con un pulsante, perché non usare semplicemente un pulsante? È possibile disattivare il bordo e in ogni caso apparirebbe come un'etichetta senza bordi. Se si desidera un bordo, è possibile incorporare un pulsante senza bordi in una NSBox. – rdelmar

7

avuto lo stesso problema. La risposta accettata qui non ha funzionato per me. Dopo molte difficoltà, ha funzionato magicamente quando ho selezionato "Nessuno" rispetto al predefinito "Normale", mentre l'altra opzione era "Elenco fonti" per l'opzione "Evidenzia" della vista tabella in IB!

Modifica: la risposta accettata risulta fuorviante poiché il metodo deve essere sovraccaricato per la vista tabella e non per il campo di testo come suggerisce la risposta. È dato più chiaramente al https://stackoverflow.com/a/13579469/804616 ma in ogni caso, essere più specifici si sente un po 'hacky.

+0

questo non funziona. forse hai fatto qualcos'altro –

+2

sembra che questo funzioni effettivamente. Stavo cercando di attivare mouseUp, ma questo non funziona con entrambi i metodi. MouseDown funziona con entrambi –

+0

Mentre funziona, cosa succede se si desidera che la vista tabella utilizzi lo stile di visualizzazione della tabella dell'elenco di origine? –

1

Nella stessa identica situazione, l'incorporamento di NSButton con transparent impostato su true/YES ha funzionato per me.

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

Si utilizza window.makeFirstResponser (myTextfield) per iniziare a modificare il campo di testo. Si invia questo messaggio dal metodo overdride mouseDown (withEvent TheEvent: NSEvent)