Как изменить цвет текста NSTextField при выборе строки? - программирование

Как изменить цвет текста NSTextField при выборе строки?

Для cocoa у меня установлен NSTableView, который должен быть основан на представлении. Когда строка выбрана, текстовые поля меняют цвет на белый. Как сохранить его черным?

Я также должен отметить, что в элементе Highlight установлен список источников (он делает то же самое в Regular). Highlight Setting

Невыбранная строка Unselected

Выбранная строка Selected Row

Я надеялся на что-то похожее на конфигурацию состояния для iOS:

enter image description here

Это было предложено на WWDC 2011 Session 120, но оно немного задержалось, поэтому я не буду его использовать. Это может работать для кого-то еще.

- (void)tableViewSelectionDidChange:(NSNotification *)notification
{
    [tableView enumerateAvailableRowViewsUsingBlock:^(NSTableRowView *rowView, NSInteger row){
        NSTableCellView *cellView = [rowView viewAtColumn:0];
        if(rowView.selected){
            cellView.textField.font = [NSFont boldSystemFontOfSize:14];
        }else{
            cellView.textField.font = [NSFont systemFontOfSize:14];
        }
    }];
}
4b9b3361

Ответ 1

В зависимости от того, зачем вам это нужно, есть 2 подхода.

Вы можете подклассифицировать NSTableRowView и переопределить -[NSTableRowView interiorBackgroundStyle], чтобы вернуть NSBackgroundStyleLight. Это скажет клеткам, что они находятся на светлом фоне и нарисовать темный текст, который будет черным.

Другим способом является подкласс NSTableCellView и переопределить -[NSTableCellView setBackgroundStyle:] и сами установить цвета.

Ответ 2

Переопределите NSTableCellView и добавьте этот метод для изменения цвета текста при выборе ячейки.

- (void) setBackgroundStyle:(NSBackgroundStyle)backgroundStyle
{
    NSTableRowView *row = (NSTableRowView*)self.superview;
    if (row.isSelected) {
        self.textField.textColor = [NSColor blackColor];
    } else {
        self.textField.textColor = [NSColor whiteColor];
    }

}

Ответ 3

Для этого не требуется настраиваемый код.

Просто установите цвет метки в "Цвет ярлыка" в Interface Builder. Автоматическая белая/черная вещь работает только в том случае, если метка имеет "Цвет контрольного текста" и находится в NSTableCellView.

Ответ 4

Для моего приложения Swift ни одно из вышеизложенных показалось, что оно не работает корректно. Этот метод правильно обрабатывает NSTableView, теряя фокус, и когда окно не является ключевым окном, но ячейка по-прежнему выбрана.

В подклассе NSTableCellView используйте следующее:

override var backgroundStyle: NSView.BackgroundStyle {
  willSet {
    if newValue == .dark {
      title.textColor = NSColor.white
    } else {
      title.textColor = NSColor.labelColor
    }
  }
}

Ответ 5

На основе ответа @sabes я создал этот подкласс NSTextFieldCell, который вы можете использовать для установки ваших пользовательских цветов текста, когда строка выбрана или отменена. Вы можете установить подкласс соответствующей ячейки текстового поля в IB.

@interface SNBlueTextFieldCell : NSTextFieldCell

@end

@implementation SNBlueTextFieldCell

- (void)setBackgroundStyle:(NSBackgroundStyle)backgroundStyle {
    [self setTextColor:(backgroundStyle==NSBackgroundStyleDark ? [NSColor blackColor] : [NSColor blueColor])];
}

@end

Ответ 6

Я придумал другое решение. Подклассификация NSTableCellView была бы прекрасной, если Cocoa поддерживается @IBOutletCollection. Потому что тогда у меня мог бы быть один подкласс класса, в котором есть массив всех NSTextFields в ячейке. Но поскольку у меня было много типов ячеек с различным количеством NSTextFields, мне не понравился этот вариант. Вместо этого я взглянул на документацию Apple для свойства backgroundStyle в NSTableCellView.

Реализация по умолчанию автоматически переадресовывает вызовы во все подзадачи, которые реализуют setBackgroundStyle: или являются NSControl, которые имеют классы NSCell, которые отвечают на backgroundStyle.

Если мои TextFields реализуют setBackgroundStyle, тогда они должны получать уведомление, когда выбор ячейки изменяется. Однако эта пересылка стиля фона не является рекурсивной. Поскольку мои NSTextFields были в NSStackViews, они не получали сообщение. Чтобы обойти это, я просто написал расширение для реализации setBackgroundStyle во всех NSView. Он просто пересылает сообщение. Наконец, я добавил расширение для NSTextField, чтобы реализовать этот метод. Из этого расширения я меняю цвет текста и звоню супер. Это решение также хорошо, потому что никаких подклассов не требуется. Нет подклассов NSTableCellView или NSTextField.

Добавление этой функциональности ко всем представлениям и ко всем NSTextFields может вызвать проблемы с NSTextFields, которые не входят в NSTableViews, меняя цвет неожиданно. Но до сих пор только те, что были в моем TableViews/OutlineViews, меняют цвет, и это именно то, что я искал. Если вы видите, что текстовые поля меняют цвет, чего вы не ожидаете, вы можете захотеть подкласса NSTextField и реализовать переопределение setBackgroundStyle только в этом подклассе, а не добавлять его ко всем NSTextFields.

Код в Swift 3, который я использовал, вставлен ниже.

extension NSView {
    func setBackgroundStyle(_ newValue: NSBackgroundStyle) {
        for view in self.subviews {
            view.setBackgroundStyle(newValue)
        }
    }
}

extension NSTextField {
    override func setBackgroundStyle(_ newValue: NSBackgroundStyle) {
        switch newValue {
        case .dark:
            self.textColor = NSColor.controlLightHighlightColor
        case .light, .lowered, .raised:
            self.textColor = NSColor.labelColor
        }
        super.setBackgroundStyle(newValue)
    }
}