выберите текст NSTextField в фокусе - PullRequest
11 голосов
/ 04 февраля 2010

Может ли кто-нибудь предложить метод выделения всего текста NSTextField, когда пользователь щелкает по нему?

Я нашел предложения для подкласса NSTextField, а затем использовал mouseDown или firstResponder, `но сейчас это не в моих силах. Поэтому я надеялся, что или будет более простое решение, или кто-то может быть достаточно любезен, чтобы подробно описать необходимые шаги.

Ответы [ 4 ]

23 голосов
/ 04 февраля 2010

Нет более простого решения, вам нужно создать подкласс NSTextField, чтобы делать то, что вы хотите.Вам нужно будет научиться обращаться с подклассами, если вы хотите сделать что-нибудь полезное в Какао.

Текстовые поля могут быть относительно сложными для подкласса, потому что NSTextField использует отдельный объект NSTextView, называемый Редактором полей дляобрабатывать фактическое редактирование.Это текстовое представление возвращается объектом NSWindow для NSTextField и повторно используется для всех текстовых полей на странице.

Как и любой подкласс NSResponder, NSTextField отвечает на методы-acceptsFirstResponder и -becomeFirstResponder.Они вызываются, когда окно хочет выделить определенный элемент управления или представление.Если вы вернете YES от обоих этих методов, то ваш элемент управления / представление будет иметь статус первого респондента, что означает, что это активный элемент управления.Однако, как уже упоминалось, NSTextField на самом деле дает полевому редактору статус первого респондента при нажатии, поэтому вам нужно сделать что-то подобное в своем подклассе NSTextField:

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

Это сначала вызывает реализацию суперкласса-becomeFirstResponder, который сделает тяжелую работу по управлению редактором поля.Затем он вызывает -selectText:, который выделяет весь текст в поле, но делает это после задержки в 0 секунд, которая будет задерживаться до следующего запуска цикла обработки событий.Это означает, что выбор произойдет после того, как редактор полей будет полностью настроен.

5 голосов
/ 21 октября 2015

Ответ от @Rob предположительно работал в какой-то момент, но, как заметил @Daniel, он больше не работает.Похоже, что Какао хочет отследить мышь и вытянуть выделение в ответ на щелчок, и попытка выделить текст в ответ на becomeFirstResponder не очень хорошо с этим справляется.

Событию мыши нужнобыть перехвачен, чтобы предотвратить это отслеживание.Более или менее методом проб и ошибок я нашел решение, которое, похоже, работает на OS X 10.10:

@interface MyAutoselectTextField : NSTextField
@end

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

Насколько я могу судить, к тому времени, когда mouseDown: будет вызван редактором полейуже был настроен, вероятно, как побочный эффект becomeFirstResponder.Вызов selectAll: затем выбирает содержимое редактора полей.Вызов selectText: на self вместо этого не работает должным образом, предположительно, потому что установлен редактор полей.Обратите внимание, что переопределение mouseDown: здесь не call super;super запускает цикл отслеживания, который вытягивает выделение, и мы не хотим такого поведения.Обратите внимание, что это mouseDown: переопределение не влияет на выбор, когда текстовое поле стало первым респондентом, потому что в этот момент вызывается mouseDown: редактора поля.

Я не знаю, какой диапазонВерсии OS X это работает через;если вам это нужно, вам нужно проверить это.К сожалению, работа с NSTextField всегда немного хрупкая, потому что методы работы полевых редакторов очень странные и зависят от деталей реализации в super.

2 голосов
/ 13 октября 2015

Некоторые обновления со Swift:

import Cocoa

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

Или для точного выбора:

import Cocoa

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

Swift, у меня работает:

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
    }
}
1 голос
/ 05 мая 2017

Мне нравится решение Константина, но оно будет выбираться при каждом нажатии мыши.Вот вариант, который я использую для выбора в mouseDown методе, но только если он только стал первым респондентом:

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
        }
    }
}
...