[Cocoa]_[NSTableView]_[添加复选框]

要想给tableview添加复选框就要重定义那一列的cell,通过重写绘图事件和点击事件来实现。

1.重定义cell

YepCheckImageCell.h

#import <Cocoa/Cocoa.h>

@interface YepCheckImageCell : NSButtonCell
{
    BOOL isChecked;
    NSImage* checkImage[2];
    NSUInteger imageOffset;
}

@property (readwrite,assign) BOOL isChecked;

@end

YepCheckImageCell.m

#import "YepCheckImageCell.h"

@implementation YepCheckImageCell

@synthesize isChecked;

-(void)awakeFromNib
{
    //初始化复选框图片
    NSString *checkPath = [[NSBundle mainBundle] pathForResource:@"check-yes" ofType:@"png"];
    checkImage[1] = [[NSImage alloc] initByReferencingFile:checkPath];
    
    NSString *uncheckPath = [[NSBundle mainBundle] pathForResource:@"check-no" ofType:@"png"];
    checkImage[0] = [[NSImage alloc] initByReferencingFile:uncheckPath];
    
    //设置偏移量
    imageOffset = 6;
}

-(NSRect)drawTitle:(NSAttributedString *)title withFrame:(NSRect)frame inView:(NSView *)controlView
{
    NSRect imageRect = frame;
    NSImage *image = checkImage[isChecked];
    imageRect.origin.x += imageOffset;
    imageRect.origin.y += (imageRect.size.height - image.size.height)/2;
    imageRect.size = image.size;
    [image drawInRect:imageRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1 respectFlipped:YES hints:nil];
    frame.origin.x += image.size.width + imageOffset * 2;
    return [super drawTitle:title withFrame:frame inView:controlView];
}

-(BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame ofView:(NSView *)controlView untilMouseUp:(BOOL)flag
{
    //如果不是点击事件直接返回
    if([theEvent type]!= NSLeftMouseDown)
    {
        return NSCellHitContentArea;
    }
    
    //获取点击坐标在表格的行数
    NSTableView *myView = (NSTableView *)controlView;
    NSPoint p = [theEvent locationInWindow];
    NSPoint local_point = [myView convertPoint:p fromView:nil];    
    NSUInteger row = [myView rowAtPoint:local_point];
    
    NSImage *image = checkImage[isChecked];
    
    //判断点击的位置是在复选框内
    if (local_point.x >= imageOffset && local_point.x <= (image.size.width + imageOffset)) {
        
        [[myView delegate] performSelector:@selector(setCheckItem:) withObject:[NSNumber numberWithInteger:row]];
        return NSCellHitContentArea;
    }
    
    return NSNullCellType;
}

@end

2.自定义表头添加一键全选功能

YepTableHeaderView.h

#import <Cocoa/Cocoa.h>

@interface YepTableHeaderView : NSTableHeaderView
{
    NSImage* checkImage[2];
    BOOL isChecked;
    int imageOffset;
}

@end

YepTableHeaderView.m

#import "YepTableHeaderView.h"

@implementation YepTableHeaderView

- (id)initWithFrame:(NSRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here.
    }
    
    return self;
}

-(void)awakeFromNib
{
    NSString* checkPath = [[NSBundle mainBundle] pathForResource:@"check-yes" ofType:@"png"];
    checkImage[1] = [[NSImage alloc] initByReferencingFile:checkPath];
    
    NSString* uncheckPath = [[NSBundle mainBundle] pathForResource:@"check-no" ofType:@"png"];
    checkImage[0] = [[NSImage alloc] initByReferencingFile:uncheckPath];
    
    isChecked = 0;
    imageOffset = 9;
}

- (void)drawRect:(NSRect)dirtyRect
{
    // Drawing code here.
    NSArray* tableColumn = [[self tableView ]tableColumns];
    
    //画背景
    [[NSColor lightGrayColor] set];
    NSRectFill(dirtyRect);
    
    //画复选框
    NSImage* image = checkImage[isChecked];
    NSRect imageRect = dirtyRect;
    imageRect.origin.x = imageOffset;
    imageRect.origin.y = imageRect.origin.y+(imageRect.size.height - image.size.height)/2;
    imageRect.size = image.size;
    
    [image drawInRect:imageRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1 respectFlipped:YES hints:nil];
    
    //画表头标题
    for (int i = 0; i < tableColumn.count ; ++i)
    {
        [[NSColor colorWithCalibratedRed: 38/255.0 green:38/255.0 blue:38/255.0 alpha:1]  setStroke];
        NSTableColumn* column = [tableColumn objectAtIndex:i];
        NSRect rect = [self headerRectOfColumn:i];
        NSPoint buttomBegin = rect.origin;
        NSPoint buttomEnd = buttomBegin;
        buttomEnd.y += rect.size.height;
                
        NSString* headerStr = [[column headerCell] stringValue];
        NSColor *txtColor = [NSColor colorWithCalibratedRed: 120/255.0 green:127/255.0 blue:133/255.0 alpha:1];
        NSFont *txtFont = [NSFont systemFontOfSize:14];
        
        NSSize size = [headerStr sizeWithAttributes:nil];
        NSPoint pb = rect.origin;
        pb.x += 4;
        if (i==0)
        {
            pb.x += checkImage[0].size.width + 10;
            txtColor = [NSColor colorWithCalibratedRed: 0.0 green:0.0 blue:0.0 alpha:1];
            txtFont =[NSFont fontWithName:@"Arial" size:12];
        }
        if (i>=1) {
            //pb.x +=5;
            txtColor = [NSColor colorWithCalibratedRed: 99/255.0 green: 99/255.0 blue: 99/255.0 alpha:1];
            txtFont =[NSFont fontWithName:@"Arial" size:12];
            
        }
        NSDictionary *txtDict = [NSDictionary dictionaryWithObjectsAndKeys:
                                 txtFont, NSFontAttributeName, txtColor, NSForegroundColorAttributeName, nil];
        NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:headerStr attributes:txtDict];
        
        pb.y = rect.origin.y+(rect.size.height - size.height)/2;
        [attrStr drawAtPoint:pb];
    }
    
    [[NSColor colorWithCalibratedRed: 0/255.0 green:0/255.0 blue:0/255.0 alpha:0.5] setStroke];
}

- (void)mouseDown:(NSEvent *)theEvent
{
    isChecked = !isChecked;
    NSSize size = [checkImage[isChecked] size];
    NSPoint p = [theEvent locationInWindow];
    NSPoint local_point = [self convertPoint:p fromView:nil];
    
    NSRect imageRect = self.frame;
    local_point.y = imageRect.origin.y;
    
    CGFloat xr = imageOffset+size.width+20;
    imageRect.origin.x = xr;
    imageRect.size.width = size.width;
    imageRect.size.height = size.height;
    
    if (local_point.x<xr && local_point.x > imageOffset)
    {
        NSTableView *myView = [self tableView];
       
        [myView.delegate performSelector:@selector(setHeaderCheckItem:) withObject:[NSNumber numberWithInteger:isChecked]];
        
        [self setNeedsDisplay:YES];
    }
    //1.如果调用父的mouseDown,MouseUp就不会调用.
    [super mouseDown:theEvent];
}

@end

3.在表格代理类种定义函数来改变表格数据,这里用的是setCheckItem,根据行号来动态修改复选框的状态

-(void) setCheckItem:(id) data
{
    NSNumber *row = data;
    SimpleData *item = [array objectAtIndex:row.integerValue];
    [item setIsChecked:!item.isChecked];
    NSIndexSet *rowSet = [NSIndexSet indexSetWithIndex:[row integerValue]];
    NSIndexSet *columnSet = [NSIndexSet indexSetWithIndex:0];
    [tableView reloadDataForRowIndexes:rowSet columnIndexes:columnSet];
}

4.在表格代理类中定义函数来全选

-(void) setHeaderCheckItem:(id) data
{
    NSNumber *value = data;
    for (SimpleData *data in array) {
        [data setIsChecked:[value boolValue]];
    }
    [tableView reloadData];
}

表头最右边是需要重绘的,这里自定义一个view:

YepTableCornerView.h

#import <Cocoa/Cocoa.h>

@interface YepTableCornerView : NSView

@end
YepTableCornerView.m

#import "YepTableCornerView.h"

@implementation YepTableCornerView

- (id)initWithFrame:(NSRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here.
    }
    
    return self;
}

- (void)drawRect:(NSRect)dirtyRect
{
    // Drawing code here.
    //填充角view的颜色
    [[NSColor colorWithCalibratedRed: 255/255.0 green:255/255.0 blue:255/255.0 alpha:1] setFill];
    NSRectFill(dirtyRect);
    
    //画角view的边
    NSBezierPath *line = [NSBezierPath bezierPath];
    [line setLineWidth:1];
    [[NSColor colorWithCalibratedRed: 255/255.0 green:255/255.0 blue:255/255.0 alpha:1] setStroke];
    
    NSPoint endPoint = dirtyRect.origin;
    endPoint.x += dirtyRect.size.width;
    [line moveToPoint:dirtyRect.origin];
    [line lineToPoint:endPoint];
    [line stroke];
    
    NSPoint buttomBegin = dirtyRect.origin;
    buttomBegin.y += dirtyRect.size.height;
    NSPoint buttomEnd = endPoint;
    buttomEnd.y += dirtyRect.size.height;
    [line moveToPoint:buttomBegin];
    [line lineToPoint:buttomEnd];
    [line stroke];
}

@end

表格代理类中要主动调用设置表格角view

    YepTableCornerView *coreView = [[YepTableCornerView alloc] init];
    [tableView setCornerView:coreView];

5.效果:

[Cocoa]_[NSTableView]_[添加复选框]_第1张图片

项目代码例子下载地址:http://download.csdn.net/detail/yepeng2014/9184111

要是NSTableView不懂的可以参考这篇:http://blog.csdn.net/yepeng2014/article/details/49026773

你可能感兴趣的:([Cocoa]_[NSTableView]_[添加复选框])