NSTableView 中 Check 类型的 NSButtonCell 不允许更改值

发布于 2024-12-14 20:21:32 字数 976 浏览 1 评论 0原文

我有一个带有 3 个表格视图的窗口(10.7.2,Xcode 4.2)。 它们都是在 IB 中创建的,并且 NSButtonCells 与出口相连。

我创建了控制器类,并用一些示例数据填充了所有三个视图:

- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView {
    return 10;
}

- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn    *)aTableColumn row:(NSInteger)rowIndex {

NSButtonCell *buttonCell;

if(aTableView == dimensionTable) {    
    [dimensionButtonCell setTitle:@"Dimension"];
    buttonCell = dimensionButtonCell;
}
else if(aTableView == shopTable) {
    [shopButtonCell setTitle:@"Shop"];
    buttonCell = shopButtonCell;
}
else if(aTableView == countryTable) {
    [countryButtonCell setTitle:@"Country"];
    buttonCell = countryButtonCell;
}


return buttonCell;

}

我有 2 个问题:

  1. 我无法通过 GUI 更改复选框状态。不过,我可以通过编程方式更改它。当您按住鼠标按钮时,它会闪烁一点,但不允许更改...

  2. 我尝试像使用视图一样填充数据,但没有到单元格的出口。它不起作用。单元格视图中的 NSButtonCell 单元格与基于视图的表视图或基于“正常”单元格的表视图有什么不同吗?

I have window with 3 table views (10.7.2, Xcode 4.2).
They are all created in IB and NSButtonCells are connected with outlets.

I created controller class and I filled all three views with some sample data:

- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView {
    return 10;
}

- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn    *)aTableColumn row:(NSInteger)rowIndex {

NSButtonCell *buttonCell;

if(aTableView == dimensionTable) {    
    [dimensionButtonCell setTitle:@"Dimension"];
    buttonCell = dimensionButtonCell;
}
else if(aTableView == shopTable) {
    [shopButtonCell setTitle:@"Shop"];
    buttonCell = shopButtonCell;
}
else if(aTableView == countryTable) {
    [countryButtonCell setTitle:@"Country"];
    buttonCell = countryButtonCell;
}


return buttonCell;

}

I have 2 questions:

  1. I cannot change checkbox state through GUI. I can change it programatically, though. It blinks a bit, when you hold down mouse button, but doesn't allow change...

  2. I tried to fill data as with views, without outlets to cells. It didn't work. Are NSButtonCell cels within cell views somehow different as view based Table Views or "normal" cel based Table Views?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

っ〆星空下的拥抱 2024-12-21 20:21:32

经过长期的努力,我设法找到了问题的解决方案。问题的一部分是数据模型方面的简单错误,但这并不重要,更困难的是使用 NSTableView 委托和数据源来完成。

主要有 3 个困难阻碍了对这个问题的良好理解和管理:

  • 苹果的文档缺乏关于 - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *) 的差异和典型用法的任何合理解释表视图数据源中的 aTableColumn row:(NSInteger)rowIndex- (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row 其委托。虽然您似乎需要后一种方法,但因为 NSButtonCells 是自定义 NSCells,所以事实证明这是没有必要的,但我还是把它留在了最后。

  • NSTableView 方法中的内部转换

  • 网络上几乎任何地方都没有记录问题

以下是您应该执行的步骤

- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex {

    buttonCell = [aTableColumn dataCell];

    NSString *columnKey = [aTableColumn identifier];

    return buttonCell;

}

:可以看到这个方法无论你使用与否都必须实现。

- (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {

    buttonCell = [tableColumn dataCell];

    NSString *columnKey = [tableColumn identifier];

    if(tableView == dimensionTable) {    

//        returnObject = @"Dimension";
        //        [dimensionButtonCell setTitle:@"Dimension"];
        //        buttonCell = dimensionButtonCell;
    }

    else if(tableView == shopTable) {

        [buttonCell setState:[[mySelectedShops objectAtIndex:row] integerValue]];
        [buttonCell setTitle:[myShops objectAtIndex:row]];

    }

    else if(tableView == countryTable) {

        [buttonCell setState:[[mySelectedCountries objectAtIndex:row] integerValue]];
        [buttonCell setTitle:[myCountries objectAtIndex:row]];

    }

    return buttonCell;

}

您可以看到我使用了第二种方法,但是可以单独使用objectValueForTableColumn
您还可以看到,我有 NSMutableArray mySelectedShops 和 mySelectedCountries 来为表视图中的每一行保存包裹在 NSNumber 中的 NSInteger (1 或 0)。

如果设置 NSCell 的 state 或 integerValue 没有区别。两者都会检查和取消检查 NSButtonCell 的 NSInteger 类型值为 1 或 0。

- (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex {

    NSString *columnKey = [aTableColumn identifier];

    if(aTableView == dimensionTable) {    
//        [dimensionButtonCell setTitle:@"Dimension"];
//        buttonCell = dimensionButtonCell;
    }
    else if(aTableView == shopTable) {

        [mySelectedShops replaceObjectAtIndex:rowIndex withObject:[NSNumber numberWithInteger:[(NSCell*)anObject integerValue]]];

    }
    else if(aTableView == countryTable) {

        [mySelectedCountries replaceObjectAtIndex:rowIndex withObject:[NSNumber numberWithInteger:[(NSCell*)anObject integerValue]]];

    }

}

虽然我将 NSInteger 值传递给 NSCell 对象,但这里的 anObject 是 __NSCFBoolean 类型,这意味着某些内容无法按预期工作。为了能够将对象值替换为数组,我将其转换为 NSCell 只是为了获取整数值。实际上它也可以在没有演员的情况下工作,所以这对我来说是另一个谜,但我更喜欢这种方式。

很明显,Apple 正在转向基于视图的单元格,例如 UITableView。尽管如此,我希望这会对某人有所帮助。

After long struggle I manage to find the solution for the problem. One part of the problem was simple bug at the data model side, but it wasn't crucial, something much more difficult was to be done with NSTableView delegate and datasource.

THere were mainly 3 difficulties that prevented good understanding and managing this problem:

  • apple's documentation lacks of any reasonable explanation about differences and typical usage of - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndexin table view's data source and - (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row of its delegate. While it may seem that you would need latter method, because NSButtonCells are custom NSCells it turns out it is not necessary, but I left it at the end anyway.

  • internal conversions in NSTableView methods

  • problem is not documented almost anywhere on the net

Here are steps you should do:

- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex {

    buttonCell = [aTableColumn dataCell];

    NSString *columnKey = [aTableColumn identifier];

    return buttonCell;

}

You can see this method has to be implemented whether you use it or not.

- (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {

    buttonCell = [tableColumn dataCell];

    NSString *columnKey = [tableColumn identifier];

    if(tableView == dimensionTable) {    

//        returnObject = @"Dimension";
        //        [dimensionButtonCell setTitle:@"Dimension"];
        //        buttonCell = dimensionButtonCell;
    }

    else if(tableView == shopTable) {

        [buttonCell setState:[[mySelectedShops objectAtIndex:row] integerValue]];
        [buttonCell setTitle:[myShops objectAtIndex:row]];

    }

    else if(tableView == countryTable) {

        [buttonCell setState:[[mySelectedCountries objectAtIndex:row] integerValue]];
        [buttonCell setTitle:[myCountries objectAtIndex:row]];

    }

    return buttonCell;

}

you can see I used second method, however objectValueForTableColumn could be used solely.
You can also see, I have NSMutableArray mySelectedShops and mySelectedCountries to hold NSInteger (1 or 0) wrapped in NSNumber for each row in Table View.

If you set the state or integerValue of NSCell makes no difference. Both will check and uncheck NSButtonCell with values 1 or 0 of NSInteger type.

- (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex {

    NSString *columnKey = [aTableColumn identifier];

    if(aTableView == dimensionTable) {    
//        [dimensionButtonCell setTitle:@"Dimension"];
//        buttonCell = dimensionButtonCell;
    }
    else if(aTableView == shopTable) {

        [mySelectedShops replaceObjectAtIndex:rowIndex withObject:[NSNumber numberWithInteger:[(NSCell*)anObject integerValue]]];

    }
    else if(aTableView == countryTable) {

        [mySelectedCountries replaceObjectAtIndex:rowIndex withObject:[NSNumber numberWithInteger:[(NSCell*)anObject integerValue]]];

    }

}

Although I passed NSInteger value to NSCell object, anObject here is of __NSCFBoolean type, which means something doesn't work as expected. To be able to replace object value to arrays I have casted it to NSCell only to get integerValues. It actually works without cast as well, so it is another mystery to me, but I like it more that way.

It is clear Apple is moving to view based cells like in UITableView. Still, I hope this will help to somebody.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文