带有NSTableView的箭头键

dre*_*lax 11 macos cocoa objective-c

是否可以使用箭头键并输入/ tab在NSTableView周围导航NSTableView的可编辑单元格?例如,我想让它感觉更像电子表格.

该应用程序的用户需要编辑相当多的单元格(但不是全部),我认为如果他们不必双击每个单元格,那么这样做会更容易.

Jak*_*ger 9

在Sequel Pro中,我们使用了一种不同的(在我看来更简单)方法:我们control:textView:doCommandBySelector:在TableView的委托中实现.很难找到这种方法 - 可以在NSControlTextEditingDelegate协议参考中找到它.(请记住,NSTableView是NSControl的子类)

简而言之,这就是我们想出的结果(我们没有覆盖左/右箭头键,因为它们用于在单元格内导航.我们使用Tab左/右)

请注意,这只是Sequel Pro源代码的一个片段,并不能正常工作

- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)command
{
    NSUInteger row, column;

    row = [tableView editedRow];
    column = [tableView editedColumn];

    // Trap down arrow key
    if (  [textView methodForSelector:command] == [textView methodForSelector:@selector(moveDown:)] )
    {
        NSUInteger newRow = row+1;
        if (newRow>=numRows) return TRUE; //check if we're already at the end of the list
        if (column>= numColumns) return TRUE; //the column count could change

        [tableContentView selectRowIndexes:[NSIndexSet indexSetWithIndex:newRow] byExtendingSelection:NO];
        [tableContentView editColumn:column row:newRow withEvent:nil select:YES];
        return TRUE;
    }

    // Trap up arrow key
    else if (  [textView methodForSelector:command] == [textView methodForSelector:@selector(moveUp:)] )
    {
        if (row==0) return TRUE; //already at the beginning of the list
        NSUInteger newRow = row-1;

        if (newRow>=numRows) return TRUE;
        if (column>= numColumns) return TRUE;

        [tableContentView selectRowIndexes:[NSIndexSet indexSetWithIndex:newRow] byExtendingSelection:NO];
        [tableContentView editColumn:column row:newRow withEvent:nil select:YES];
        return TRUE;
    }
Run Code Online (Sandbox Code Playgroud)


dre*_*lax 5

嗯,这并不容易,但我设法做到了,而不必使用 RRSpreadSheet 甚至其他控件。这是你必须做的:

  1. 创建 的子类NSTextView,这将是字段编辑器。对于此示例,MyFieldEditorClass将使用名称并将myFieldEditor引用此类的实例。

  2. 添加一个MyFieldEditorClass名为“ - (void) setLastKnownColumn:(unsigned)aCol andRow:(unsigned) aRow”的方法或类似的方法,并将两个输入参数值保存在某处。

  3. 添加另一个名为“setTableView:”的方法并将 NSTableView 对象保存在某处,或者除非有另一种方法可以从字段编辑器中获取 NSTableView 对象,否则请使用它。

  4. 添加另一个名为- (void) keyDown:(NSEvent *) event. 这实际上是覆盖了NSResponder's keyDown:。源代码应该是(请注意 StackOverflow 的 MarkDown 正在更改<并更改>&lt;&gt;):

    - (void) keyDown:(NSEvent *) event
    {
        unsigned newRow = row, newCol = column;
        switch ([event keyCode])
        {
            case 126: // Up
                if (row)
                newRow = row - 1;
                break;
    
            case 125: // Down
                if (row < [theTable numberOfRows] - 1)
                    newRow = row + 1;
                break;
    
            case 123: // Left
                if (column > 1)
                    newCol = column - 1;
                break;
    
            case 124: // Right
                if (column < [theTable numberOfColumns] - 1)
                    newCol = column + 1;
                break;
    
            default:
                [super keyDown:event];
                return;
        }
    
        [theTable selectRow:newRow byExtendingSelection:NO];
        [theTable editColumn:newCol row:newRow withEvent:nil select:YES];
        row = newRow;
        column = newCol;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  5. 给你笔尖中的 NSTableView 一个委托,并在委托中添加方法:

    - (BOOL) tableView:(NSTableView *)aTableView shouldEditColumn:(NSTableColumn *) aCol row:aRow
    {
        if ([aTableView isEqual:TheTableViewYouWantToChangeBehaviour])
            [myFieldEditor setLastKnownColumn:[[aTableView tableColumns] indexOfObject:aCol] andRow:aRow];
        return YES;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  6. 最后,给 Table View 的主窗口一个委托并添加方法:

    - (id) windowWillReturnFieldEditor:(NSWindow *) aWindow toObject:(id) anObject
    {
        if ([anObject isEqual:TheTableViewYouWantToChangeBehaviour])
        {
            if (!myFieldEditor)
            {
                myFieldEditor = [[MyFieldEditorClass alloc] init];
                [myFieldEditor setTableView:anObject];
            }
            return myFieldEditor;
        }
        else
        {
            return nil;
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

运行程序并试一试!