Реагировать на события мыши в текстовом поле в табличном представлении

У меня есть текстовые поля внутри настраиваемого представления внутри NSOutlineView . Для редактирования одной из этих ячеек требуется один щелчок, пауза и еще один щелчок. Первый одиночный щелчок выбирает строку представления таблицы, а второй одиночный щелчок рисует курсор в поле. Двойной щелчок по ячейке, который позволяет редактировать в табличном представлении на основе ячеек, выделяет только строку.

Я хочу поведение: один щелчок, чтобы изменить выделение и редактировать.

Что мне нужно изменить для получить такое поведение?

Я читал некоторые другие сообщения:

  • Легковесный шаблон NSTextField , похоже, не применим к представлениям таблиц на основе представлений, где все представления ячеек создается из перьев.
  • Я пробовал создать подкласс NSTextField , например , это решение описывает , но мой переопределенный метод mouseDown не вызывается. Переопределенные awakeFromNib и viewWillDraw (упомянутые в этот пост ) вызываются . Конечно, mouseDown вызывается, если я помещаю текстовое поле где-нибудь за пределами табличного представления.

Для сравнения, NSSegmentedControl в моем представлении ячейки изменяет свое значение без предварительного выбора строки.


Вот рабочее решение , адаптированное из принятого ответа:

В подклассе представления структуры:

-(void)mouseDown:(NSEvent *)theEvent {
    [super mouseDown:theEvent];

    // Forward the click to the row's cell view
    NSPoint selfPoint = [self convertPoint:theEvent.locationInWindow fromView:nil];
    NSInteger row = [self rowAtPoint:selfPoint];
    if (row>=0) [(CellViewSubclass *)[self viewAtColumn:0 row:row makeIfNecessary:NO]
            mouseDownForTextFields:theEvent];
}

В подклассе представления ячейки таблицы:

// Respond to clicks within text fields only, because other clicks will be duplicates of events passed to mouseDown
- (void)mouseDownForTextFields:(NSEvent *)theEvent {
    // If shift or command are being held, we're selecting rows, so ignore
    if ((NSCommandKeyMask | NSShiftKeyMask) & [theEvent modifierFlags]) return;
    NSPoint selfPoint = [self convertPoint:theEvent.locationInWindow fromView:nil];
    for (NSView *subview in [self subviews])
        if ([subview isKindOfClass:[NSTextField class]])
            if (NSPointInRect(selfPoint, [subview frame]))
                [[self window] makeFirstResponder:subview];
}

27
задан Community 23 May 2017 в 11:54
поделиться

2 ответа

Я попытаюсь вернуть услугу ... Подкласс NSOutlineView и переопределить -mouseDown: примерно так:

- (void)mouseDown:(NSEvent *)theEvent {
    [super mouseDown:theEvent];

    // Only take effect for double clicks; remove to allow for single clicks
    if (theEvent.clickCount < 2) {
        return;
    }

    // Get the row on which the user clicked
    NSPoint localPoint = [self convertPoint:theEvent.locationInWindow
                                   fromView:nil];
    NSInteger row = [self rowAtPoint:localPoint];

    // If the user didn't click on a row, we're done
    if (row < 0) {
        return;
    }

    // Get the view clicked on
    NSTableCellView *view = [self viewAtColumn:0 row:row makeIfNecessary:NO];

    // If the field can be edited, pop the editor into edit mode
    if (view.textField.isEditable) {
        [[view window] makeFirstResponder:view.textField];
    }
}
15
ответ дан 28 November 2019 в 05:32
поделиться

Просто хочу отметить, что если все, что вам нужно, это только редактирование (то есть в таблице без выбора), переопределение -hitTest: кажется более простым и более похожим на какао:

- (NSView *)hitTest:(NSPoint)aPoint
{
    NSInteger column = [self columnAtPoint: aPoint];
    NSInteger row = [self rowAtPoint: aPoint];

    // Give cell view a chance to override table hit testing
    if (row != -1 && column != -1) {
        NSView *cell = [self viewAtColumn:column row:row makeIfNecessary:NO];

        // Use cell frame, since convertPoint: doesn't always seem to work.
        NSRect frame = [self frameOfCellAtColumn:column row:row];
        NSView *hit = [cell hitTest: NSMakePoint(aPoint.x + frame.origin.x, aPoint.y + frame.origin.y)];

        if (hit)
            return hit;
    }

    // Default implementation
    return [super hitTest: aPoint];
}
1
ответ дан 28 November 2019 в 05:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: