0

I have embedded an NSTableView inside an NSScrollView as shown in this example but for some reason, setting the column width only works correctly when initially setting it. Changing it later, i.e. in response to a button click, doesn't do anything at all. I do it like this:

[col setMinWidth:1000];
[col setMaxWidth:1000];
[col setWidth:1000];

After those calls col.width correctly returns 1000 but the NSTableView doesn't show the change. It still looks as before, i.e. longer entries are still cut off using ... even though the column width is 1000 points now.

I have tried to call [tableView setNeedsDisplay:YES] after changing the column width but it doesn't help. Calling setNeedsDisplay on the NSScrollView doesn't help either. I've also tried playing with NSTableColumn's resizingMask and NSTableView's columnAutoresizingStyle but all to no avail. Trying to change the column width just doesn't work here. Any ideas?

EDIT

Here's the code for reference:

listDelegate = [[MyListDelegate alloc] initWithChoices:array];

scrollview = [[NSScrollView alloc] initWithFrame:NSMakeRect(20, 52, rect.size.width - 2 * 20, 200)];
tableview = [[NSTableView alloc] initWithFrame:NSMakeRect(0, 0, rect.size.width - 2 * 20 - 16, 200)];
column = [[NSTableColumn alloc] initWithIdentifier:@"Column"];

[column setWidth:400];
[tableview addTableColumn:column];
[tableview setHeaderView:nil];
[tableview setDelegate:listDelegate];
[tableview setDataSource:listDelegate];
[tableview reloadData];
[scrollview setDocumentView:tableview];
[scrollview setHasVerticalScroller:YES];
[scrollview setHasHorizontalScroller:YES];  
[[win contentView] addSubview:scrollview];
[scrollview release];
[column release];

The list delegate looks like this:

@interface MyListDelegate : NSObject
{
    NSArray *choices;
}
    
- (id)initWithChoices:(NSArray *)c; 
@end

@implementation MyListDelegate

- (id)initWithChoices:(NSArray *)c
{
    if(!(self = [super init])) return nil;

    choices = c;
    
    return self;
}

- (int)numberOfRowsInTableView:(NSTableView *)_tableView
{
    return (int) [choices count];
}

- (id)tableView:(NSTableView *)_tableView objectValueForTableColumn:(NSTableColumn *) tableColumn row:(int)row
{
    return [choices objectAtIndex:row];
}

- (BOOL)tableView:(NSTableView *)_tableView shouldEditTableColumn:(NSTableColumn *) tableColumn row:(int)row
{
    return NO;
}   
@end

And when the button is pressed, the following code is executed:

NSTableColumn *col = [[tableview tableColumns] objectAtIndex:0];
[col setMinWidth:1000];
[col setMaxWidth:1000];
[col setWidth:1000];
Andreas
  • 9,245
  • 9
  • 49
  • 97

2 Answers2

1

Here's one technique to change the column width of a table view.

#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate, NSTableViewDelegate, NSTableViewDataSource> {
 NSWindow *window;
 NSTableColumn *column1;
}
- (void) myBtnAction;
- (void) buildMenu;
- (void) buildWindow;
@end

@implementation AppDelegate

- (void) myBtnAction {
 [column1 setWidth:150];
}

- (void) buildMenu {
 NSMenu *menubar = [NSMenu new];
 NSMenuItem *menuBarItem = [NSMenuItem new];
 [menubar addItem:menuBarItem];
 [NSApp setMainMenu:menubar];
 NSMenu *appMenu = [NSMenu new];
 NSMenuItem *quitMenuItem = [[NSMenuItem alloc] initWithTitle:@"Quit" action:@selector(terminate:) keyEquivalent:@"q"];
 [appMenu addItem:quitMenuItem];
 [menuBarItem setSubmenu:appMenu];
}

- (void) buildWindow {

#define _wndW  500
#define _wndH  350

window = [[NSWindow alloc] initWithContentRect: NSMakeRect( 0, 0, _wndW, _wndH )
styleMask: NSWindowStyleMaskTitled | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable
backing: NSBackingStoreBuffered defer: NO];

[window center];
[window setTitle: @"Test window"];
[window makeKeyAndOrderFront: nil];

// **** TableView_SO **** //
 NSScrollView *scrlView = [[NSScrollView alloc] initWithFrame:NSMakeRect(60, 100, 380, 200)];
 NSTableView *tableView = [[NSTableView alloc] initWithFrame:NSMakeRect(0, 0, 364, 200)];
// create columns for our table
 column1 = [[NSTableColumn alloc] initWithIdentifier:@"Col1"];
 NSTableColumn * column2 = [[NSTableColumn alloc] initWithIdentifier:@"Col2"];
 [column1 setWidth:252];
 [column2 setWidth:198];
// generally you want to add at least one column to the table view.
 [tableView addTableColumn:column1];
 [tableView addTableColumn:column2];
 [tableView setDelegate:self];
 [tableView setDataSource:self];
 [tableView reloadData];
// embed table view in the scroll view, and add the scroll view to window.
 [scrlView setDocumentView:tableView];
 [scrlView setHasVerticalScroller:YES];
 [[window contentView] addSubview:scrlView];

// **** Button **** //
NSButton *myBtn =[[NSButton alloc]initWithFrame:NSMakeRect( 30, 30, 135, 30 )];
[myBtn setBezelStyle:NSBezelStyleRounded ];
[myBtn setTitle: @"Change Col1 Width"];
[myBtn setAction: @selector (myBtnAction)];
[[window contentView] addSubview: myBtn];

// **** Quit btn **** //
NSButton *quitBtn = [[NSButton alloc]initWithFrame:NSMakeRect( _wndW - 50, 5, 40, 40 )];
[quitBtn setBezelStyle:NSBezelStyleCircular ];
[quitBtn setTitle: @"Q" ];
[quitBtn setAutoresizingMask: NSViewMinXMargin];
[quitBtn setAction:@selector(terminate:)];
[[window contentView] addSubview: quitBtn];
}

- (void) applicationWillFinishLaunching: (NSNotification *)notification {
[self buildMenu];
[self buildWindow];
}

- (void) applicationDidFinishLaunching: (NSNotification *)notification {

}
@end

int main (){
 NSApplication *application = [NSApplication sharedApplication];
 AppDelegate *appDelegate = [[AppDelegate alloc] init];
 [application setDelegate:appDelegate];
 [application run];
return 0;
}

apodidae
  • 1,988
  • 2
  • 5
  • 9
  • Is the table view replaced? – Willeke Nov 13 '20 at 08:15
  • @Willeke. Good point; my solution has been edited to change just the column width. – apodidae Nov 13 '20 at 14:59
  • So the answer is to remove `setMinWidth` and `setMaxWidth`? – Willeke Nov 15 '20 at 07:57
  • @Willeke. The original question was how to change the column width of a table column so that's what the demo shows. Min and max widths may be changed with same technique. Not necessary to change min and max when col width is changed if that's your question. – apodidae Nov 15 '20 at 17:49
  • I thought the question was "Why is my code not working" and I was wondering how this answer answers that question. – Willeke Nov 16 '20 at 07:01
  • @Willeke. >Trying to change the column width just doesn't work here. I thought the question was how do I change the column width? I also thought you used my demo to get your answer (perhaps not correct). I'm also going to stop participating in this forum if I am going to get grief for giving away code. – apodidae Nov 16 '20 at 14:26
  • Please keep answering questions and add an explanation how your code (which lines) solves the issue. – Willeke Nov 17 '20 at 07:22
1

It looks like a bug to me. [col setMinWidth:1000] also sets the width to 1000 but doesn't update the table view. [col setWidth:1000] doesn't do anything because the width is 1000. Fix: set the width first:

[col setWidth:1000];
[col setMinWidth:1000];
[col setMaxWidth:1000];
Willeke
  • 14,578
  • 4
  • 19
  • 47