2010-02-03 10 views
11

¿Alguien podría sugerir un método para seleccionar todo el texto de un NSTextField cuando el usuario hace clic en él?selectText of NSTextField on focus

Encontré sugerencias para la subclase NSTextField y luego uso mouseDown o firstResponder, `pero está más allá de mis habilidades por ahora. Así que esperaba que hubiera una solución más fácil o que alguien tuviera la amabilidad de detallar los pasos requeridos.

Respuesta

23

No hay una solución más fácil, necesita la subclase NSTextField para hacer lo que desee. Tendrá que aprender a manejar la creación de subclases si va a hacer algo útil en Cocoa.

Los campos de texto pueden ser relativamente complejos para la subclase porque un NSTextField usa un objeto NSTextView separado llamado el Editor de campo para manejar la edición real. Esta vista de texto es devuelta por el objeto NSWindow para el NSTextField y se vuelve a utilizar para todos los campos de texto en la página.

Como cualquier NSResponder subclase, NSTextField responde a los métodos -acceptsFirstResponder y -becomeFirstResponder. Se llaman cuando la ventana quiere enfocar un control o vista particular. Si devuelve YES desde ambos métodos, su control/vista tendrá el estado de primera respuesta, lo que significa que es el control activo. Sin embargo, como se mencionó, una NSTextField en realidad le da el editor primer campo de estado que responde al hacer clic, por lo que necesita para hacer algo como esto en su NSTextField subclase:

@implementation MCTextField 
- (BOOL)becomeFirstResponder 
{ 
    BOOL result = [super becomeFirstResponder]; 
    if(result) 
     [self performSelector:@selector(selectText:) withObject:self afterDelay:0]; 
    return result; 
} 
@end 

Esta primera llama implementación de -becomeFirstResponder la superclase que hará el arduo trabajo de administrar el editor de campo. A continuación, llama al -selectText:, que selecciona todo el texto en el campo, pero lo hace después de un retraso de 0 segundos, que se retrasará hasta la próxima ejecución a través del bucle de evento. Esto significa que la selección ocurrirá después de que el editor de campo haya sido completamente configurado.

+0

muchas gracias, funcionó muy bien y me hizo aprender algunas cosas. que creó el archivo .m a partir del código que ya ha proporcionado, el archivo .h de este modo: import @interface MCTextField: NSTextField {} @end Y en Interface Builder, me fui a Archivo -> Leer archivo de clase, seleccioné MCTextField.h, luego cambié la clase de mi campo de texto para que fuera MCTextField. –

+0

Esta es TAMBIÉN la solución para una gran cantidad de "seleccionar texto mediante programación" general - las rutinas de selección de texto en NSTextView, por ejemplo, no se activan correctamente si se invocan directamente en muchas ocasiones, debe ponerlas en un selector de rendimiento : afterDelay: 0 llamada. Suspiro – Adam

+1

Esto no parece funcionar bien en 10.9 SDK. Cuando hago clic en el campo, obtengo un cursor intermitente a menos que puse una demora muy larga, como 1 segundo. –

2

Algunas actualizaciones con Swift:

import Cocoa 

class TextFieldSubclass: NSTextField { 
    override func mouseDown(theEvent: NSEvent) { 
     super.mouseDown(theEvent) 
     if let textEditor = currentEditor() { 
      textEditor.selectAll(self) 
     } 
    } 
} 

o para la selección precisa:

import Cocoa 

class TextFieldSubclass: NSTextField { 
    override func mouseDown(theEvent: NSEvent) { 
     super.mouseDown(theEvent) 
     if let textEditor = currentEditor() { 
      textEditor.selectedRange = NSMakeRange(location, length) 
     } 
    } 
} 

versión Swift, funciona para mí:

import Cocoa 

class TextFieldSubclass: NSTextField { 
    override func becomeFirstResponder() -> Bool { 
     let source = CGEventSourceCreate(CGEventSourceStateID.HIDSystemState) 
     let tapLocation = CGEventTapLocation.CGHIDEventTap 
     let cmdA = CGEventCreateKeyboardEvent(source, 0x00, true) 
     CGEventSetFlags(cmdA, CGEventFlags.MaskCommand) 
     CGEventPost(tapLocation, cmdA) 
     return true 
    } 
} 
4

La respuesta de @ Rob presumiblemente funcionó en un punto, pero como @Daniel no ted, ya no funciona. Parece que Cocoa quiere rastrear el mouse y arrastrar una selección en respuesta a un clic, y tratar de seleccionar el texto en respuesta al becomeFirstResponder no funciona bien con eso.

El evento del mouse debe ser interceptado, entonces, para evitar ese seguimiento. Más o menos por ensayo y error, he encontrado una solución que parece funcionar en OS X 10.10:

@interface MyAutoselectTextField : NSTextField 
@end 

@implementation MyAutoselectTextField 
- (void)mouseDown:(NSEvent *)theEvent 
{ 
    [[self currentEditor] selectAll:nil]; 
} 
@end 

Por lo que yo puedo decir, en el momento en mouseDown: es llamada el editor de campo ya se ha establecido arriba, probablemente como un efecto secundario de becomeFirstResponder. Llamando al selectAll:, luego selecciona el contenido del editor de campo. Llamar al selectText: en self en su lugar no funciona bien, presumiblemente porque el editor de campo está configurado.Tenga en cuenta que la anulación de mouseDown: aquí hace no llame al super; super ejecutaría un bucle de seguimiento que arrastraría una selección, y no queremos ese comportamiento. Tenga en cuenta que esta anulación de mouseDown: no afecta a la selección una vez que el campo de texto se ha convertido en el primero en responder, porque en ese punto es el mouseDown: del editor de campo el que recibe la llamada.

No tengo idea de qué rango de versiones de OS X esto funciona; si te importa, deberás probarlo. Desafortunadamente, trabajar con NSTextField siempre es un poco frágil porque la manera en que trabajan los editores de campo es tan extraña y depende de los detalles de implementación en super.

1

Me gusta la solución de Konstantin, pero esa seleccionará en cada mouse hacia abajo. Aquí es una variación que estoy usando para seleccionar en mouseDown método, pero sólo si sólo se convirtió en el primer nivel de respuesta:

class SelectingTextField: NSTextField { 

    var wantsSelectAll = false 

    override func becomeFirstResponder() -> Bool { 
     wantsSelectAll = true 

     return super.becomeFirstResponder() 
    } 

    override func mouseDown(with event: NSEvent) { 
     super.mouseDown(with: event) 

     if wantsSelectAll { 
      selectText(self) 
      wantsSelectAll = false 
     } 
    } 
}