У меня есть текстовые поля внутри настраиваемого представления внутри 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];
}
Я попытаюсь вернуть услугу ... Подкласс 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];
}
}
Просто хочу отметить, что если все, что вам нужно, это только редактирование (то есть в таблице без выбора), переопределение -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];
}