简体   繁体   中英

Setting NSTableColumn width to exactly the size of its widest row

I want to set the width of my NSTableColumn to the exact width of the widest entry so that the text doesn't get ellipsized by ... . To do that, I'm doing the following whenever a new text entry is inserted:

NSCell *cell = [tableView preparedCellAtColumn:0 row:idx];
NSSize size = [cell cellSize];

if(size.width > widestWidth) {
    [tableColumn setWidth:size.width];
    widestWidth = size.width;
}

Unfortunately, the width returned by cellSize seems to be a few points off because the last character still gets ellipsized by ... . I can easily solve the problem by just adding about 8 points to size.width but of course I want to avoid that because there might be different font configurations where 8 is not enough and I also want the NSTableColumn 's width to perfectly fit to that of its widest entry.

That's why I'd like to ask: How can I get the exact width of a row so that I can pass it to NSTableColumn::SetWidth so that the NSTableColumn 's width is exactly that of the widest row?

When I ran an old cell-based demo with manual reference counting and used method dataCellForTableColumn: to measure [cell cellSize].width I got the values shown in the first image for the array items listed. When I set the column width to 60 (by rounding longest string length of 59.33 up) there was no problem. When I set the col width to 59 (by rounding down) I got the ellipsis for Charge.... I can not explain why 'Bengals' has a greater cell width than 'Chargers'. The 'team' was taken from another method, objectValueForTableColumn: and my have something to do with the order in which they are called? Second image shows the correct result by rounding up the greatest cell width.

在此处输入图像描述

在此处输入图像描述

I'll try and post the source if I ever get it converted to arc.

Based on the following example, it appears that [cell cellSize].width may be used to set the column width of a cell-based table view if the greatest cellSize.width is rounded up. The source code may be run in Xcode by replacing 'main.m' with the following and deleting the pre-supplied AppDelegate.

#import <Cocoa/Cocoa.h>

 @interface AppDelegate : NSObject <NSApplicationDelegate, NSTableViewDelegate,  NSTableViewDataSource> {
  NSWindow *window;
 }
 @property(strong, nonatomic) NSArray *teams;
 - (void) createMenu;
 - (void) createWindow;
 @end
 
 @implementation AppDelegate
 
- (id)init{
 if(self = [super init])
 _teams = [NSArray arrayWithObjects:@"Ravens", @"Chiefs", @"Chargers", @"Bengals", nil];
 NSLog(@"teams = %@",_teams);
 return self;
}

- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
 NSLog(@"count = %lu", [_teams count]);
 return [_teams count];
}

- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
 NSString *team = [_teams objectAtIndex:row];
 NSLog(@"team = %@",team);
 return [_teams objectAtIndex:row];
}

- (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)col row:(NSInteger)row {
 NSTextFieldCell *cell = [col dataCell];
 [cell setBackgroundColor: [NSColor redColor]];
 [cell setDrawsBackground:YES];
 NSSize size = [cell cellSize];
 NSLog(@"cell width = %0.02f",size.width);
 return cell;
}

 - (void) createMenu {
 NSMenu *menubar = [NSMenu new];
 NSMenuItem *appMenuItem = [NSMenuItem new];
 [menubar addItem:appMenuItem];
 [NSApp setMainMenu:menubar];
 NSMenu *appMenu = [NSMenu new];
 NSMenuItem *quitMenuItem = [[NSMenuItem alloc] initWithTitle:@"Quit"
 action:@selector(terminate:) keyEquivalent:@"q"];
 [appMenu addItem:quitMenuItem];
 [appMenuItem setSubmenu:appMenu];
 }
 
 - (void) createWindow {
 #define _wndW  300
 #define _wndH  300
 window = [[NSWindow alloc] initWithContentRect: NSMakeRect( 0, 0, _wndW, _wndH )
 styleMask: NSWindowStyleMaskTitled | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskClosable backing: NSBackingStoreBuffered defer: NO];
 [window center];
 [window setTitle:@"Test window"];
 [window makeKeyAndOrderFront: nil];
 
// **** Table View with Scroll **** //
 NSScrollView * scrollView = [[NSScrollView alloc] initWithFrame:NSMakeRect( 20, _wndH - 230, _wndW - 40, 200)];
 [scrollView setBorderType:NSBezelBorder];
 [scrollView setHasVerticalScroller:YES];
 [scrollView setAutohidesScrollers:YES];
 
 NSTableView *tableView = [[NSTableView alloc] initWithFrame:NSMakeRect(0, 0, 180, 200)];
 NSTableColumn *column1 = [[NSTableColumn alloc] initWithIdentifier:@"Col1"];
 [[column1 headerCell] setStringValue:@"Teams"];
 //Change this to 59 to see ellipsis : longest [cell cellSize].width = 59.33
 [column1 setWidth: 60];
 [tableView addTableColumn:column1];
 [tableView setDelegate:self];
 [tableView setDataSource:self];
 [tableView reloadData];
 
 // **** Embed table view into scroll view, and add scroll view to window
 [scrollView setDocumentView:tableView];
 [[window contentView] addSubview:scrollView];
  
// ***** Quit btn ***** //
 NSButton *quitBtn = [[NSButton alloc]initWithFrame:NSMakeRect( _wndW - 50, 5, 40, 40 )];
 [quitBtn setBezelStyle:NSBezelStyleCircular ];
 [quitBtn setTitle: @"Q" ];
 [quitBtn setAction:@selector(terminate:)];
 [[window contentView] addSubview: quitBtn];

 }
 
 - (void) applicationWillFinishLaunching: (NSNotification *)notification {
 [self createMenu];
 [self createWindow];
 }
 
 - (void) applicationDidFinishLaunching: (NSNotification *)notification {
 }
 @end
 
 int main() {
  NSApplication *application = [NSApplication sharedApplication];
  AppDelegate *myDelegate = [[AppDelegate alloc] init];
  [application setDelegate:myDelegate];
  [application run];
  return 0;
 }
 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM