Clickable url link in NSTextFieldCell inside NSTab

2019-03-28 12:31发布

I have a NSAttributedString that I'm using in a NSTextFieldCell. It makes several clickable url links and puts a big NSAttributedString inside the NSTextFieldCell. Whenever I am viewing the NSTextFieldCell normally and it's highlighted, I cannot click on the links.

If I set the TableView so I can edit each column or row, when I click twice, go into Edit mode and view the NSTextFieldCell contents, my links show up and are clickable. When I click away from the row, I can no longer see clickable links.

I have to be in "edit" mode to see the links or click on them.

I feel like there's some setting I'm just missing.

2条回答
【Aperson】
2楼-- · 2019-03-28 13:08

Have you seen this technical note from Apple regarding hyperlinks?

Embedding Hyperlinks in NSTextField and NSTextView

查看更多
做自己的国王
3楼-- · 2019-03-28 13:15

I don't think the tech note answers the question, which was how to put a link in an NSTableView cell. The best way I've found to do this is to use a button cell for the table cell. This assumes that only links will be in a particular column of the table.

In Interface Builder, drag an NSButton cell onto the table column where you want the links.

In your table view delegate, implement tableView:dataCellForTableColumn:row: as follows:

- (NSCell *) tableView: (NSTableView *) tableView
    dataCellForTableColumn: (NSTableColumn *) column
    row: (NSInteger) row
{
    NSButtonCell *buttonCell = nil;
    NSAttributedString *title = nil;
    NSString *link = nil;
    NSDictionary *attributes = nil;

// Cell for entire row -- we don't do headers
    if (column == nil)
        return(nil);

// Columns other than link do the normal thing
    if (![self isLinkColumn:column]) // Implement this as appropriate for your table
        return([column dataCellForRow:row]);

// If no link, no button, just a blank text field
    if ((link = [self linkForRow:row]) != nil) // Implement this as appropriate for your table
        return([[[NSTextFieldCell alloc] initTextCell:@""] autorelease]);

// It's a link. Create the title
    attributes = [[NSDictionary alloc] initWithObjectsAndKeys:
        [NSFont systemFontOfSize:[NSFont systemFontSize]], NSFontAttributeName,
        [NSNumber numberWithInt:NSUnderlineStyleSingle], NSUnderlineStyleAttributeName,
        [NSColor blueColor], NSForegroundColorAttributeName,
        [NSURL URLWithString:link], NSLinkAttributeName, nil];
    title = [[NSAttributedString alloc] initWithString:link attributes:attributes];
    [attributes release];

// Create a button cell
    buttonCell = [[[NSButtonCell alloc] init] autorelease];
    [buttonCell setBezelStyle:NSRoundedBezelStyle];
    [buttonCell setButtonType:NSMomentaryPushInButton];
    [buttonCell setBordered:NO]; // Don't want a bordered button
    [buttonCell setAttributedTitle:title];
    [title release];
    return(buttonCell);
}

Set the target/action for the table to your delegate and check for clicks on the link column:

- (void) clickTable: (NSTableView *) sender
{
    NSTableColumn *column = [[sender tableColumns] objectAtIndex:[sender clickedColumn]];
    NSInteger row = [sender clickedRow];
    NSString *link = nil;

    if ([self isLinkColumn:column] && (link = [self linkForRow:row]) != nil)
        [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:link]];
}

Now the link looks like a link, but a click on it is actually a button press, which you detect in the action method and dispatch using NSWorkspace.

查看更多
登录 后发表回答