2014-01-20 1 views
3

제공된 데이터에 따라 여러 열을 추가 할 수있는 동적 NSTableView가 있습니다. 각 열에 대해 머리글 셀을 NSPopUpButtonCell로 설정했습니다. (사이드 노트 : NSTableHeaderView를위한 커스텀 서브 클래스 클래스를 사용해야했다. 그렇지 않으면 메뉴가 팝업되지 않는다). 오른쪽 상단의 중복 또는 추가 머리글 단추 셀을 제외하고 모두 올바르게 작동합니다. 스크린 샷과 같이 이전 열 선택을 완벽하게 반영합니다. 내 질문에 어떻게 이전 팝업 헤더 셀을 재활용 NSTableView 중지합니까? (그런데 나는 setCornerView 방법을 시도하지만 그건 단지 수직 스크롤 바 위의 헤더 영역에 영향을 미친다.) 나는 이번 주에 같은 문제를 건너 왔어요NSPopUpButtonCell을 사용할 때 NSTableView에서 중복 머리글 단추 셀 가져 오기

Duplicate column header popupbuttoncell mirrors the selected value of the previous column

답변

1

Duplicate column header popupbuttoncell

. 나는
[_tableView sizeLastColumnToFit]; 

는 (단, 영업 이익과 협의 후이 당신이 헤더에 NSPopUpButtonCell의 서브 클래스를 사용하는 것이 필요하며 또한 NSTableHeaderView가. 내가 아래에있는 내 솔루션 첨부) 당신이 할 수있는

에를, 빠른 수정 갔다 접근 방법이 여기에 설명 된 결합하여이,

  1. PopUpTableHeaderCell
  2. DataTableHeaderView
,

는 여기에서 NSTableViewHeader 서브 클래스에 지금

// PopUpTableHeaderCell.h 
#import <Cocoa/Cocoa.h> 
/* Credit: http://www.cocoabuilder.com/archive/cocoa/133285-placing-controls-inside-table-header-view-solution.html#133285 */ 

@interface PopUpTableHeaderCell : NSPopUpButtonCell 
@property (strong) NSTableHeaderCell *tableHeaderCell; // Just used for drawing the background 

@end 

// PopUpTableHeaderCell.m 
@implementation PopUpTableHeaderCell 

- (id)init { 
    if (self = [super init]){ 

     // Init our table header cell and set a blank title, ready for drawing 
     _tableHeaderCell = [[NSTableHeaderCell alloc] init]; 
     [_tableHeaderCell setTitle:@""]; 

     // Set up the popup cell attributes 
     [self setControlSize:NSMiniControlSize]; 
     [self setArrowPosition:NSPopUpNoArrow]; 
     [self setBordered:NO]; 
     [self setBezeled:NO]; 
     [self setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; 
    } 
    return self; 
} 

// We do all drawing ourselves to make our popup cell look like a header cell 
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView{ 

    [_tableHeaderCell drawWithFrame:cellFrame inView:controlView]; 

    // Now draw the text and image over the top 
    [self drawInteriorWithFrame:cellFrame inView:controlView]; 
} 

@end 

단순화 된 조각이다.

//DataTableHeaderView.h 
#import <Cocoa/Cocoa.h> 

/* Credit: http://forums.macnn.com/79/developer-center/304072/problem-of-nspopupbuttoncell-within-nstableheaderview/ */ 

@interface DataTableHeaderView : NSTableHeaderView 
@end 

//DataTableHeaderView.m 
#import "DataTableHeaderView.h" 

/* Credit: http://forums.macnn.com/79/developer-center/304072/problem-of-nspopupbuttoncell-within-nstableheaderview/ */ 

@implementation DataTableHeaderView 

- (id)initWithFrame:(NSRect)frame { 

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

- (void)mouseDown:(NSEvent *)theEvent { 

    // Figure which column, if any, was clicked 
    NSPoint clickedPoint = [self convertPoint:theEvent.locationInWindow fromView:nil]; 
    NSInteger columnIndex = [self columnAtPoint:clickedPoint]; 
    if (columnIndex < 0) { 
     return [super mouseDown:theEvent]; 
    } 

    NSRect columnRect = [self headerRectOfColumn:columnIndex]; 

    // I want to preserve column resizing. If you do not, remove this 
    if (![self mouse:clickedPoint inRect:NSInsetRect(columnRect, 3, 0)]) { 
     return [super mouseDown:theEvent]; 
    } 

    // Now, pop the cell's menu 
    [[[self.tableView.tableColumns objectAtIndex:columnIndex] headerCell] performClickWithFrame:columnRect inView:self]; 
    [self setNeedsDisplay:YES]; 
} 

- (BOOL)isOpaque { 
    return NO; 
} 


- (void)drawRect:(NSRect)dirtyRect { 
    [super drawRect:dirtyRect]; 
    // Drawing code here. 
} 

@end 

당신은 내가 제대로 그 지역의 도면을 수정하는 방법을 알아 냈하지 않은 그 외에는

-(void) awakeFromNib { 

    /* NB the NSTableHeaderView class is changed to be an DataTableHeaderView in IB! */ 

    NSUInteger numberOfColumnsWanted = 5; 
    for (NSUInteger i=0; i<numberOfColumnsWanted; i++) { 

     PopUpTableHeaderCell *headerCell; 
     headerCell = [[PopUpTableHeaderCell alloc] init]; 

     [headerCell addItemWithTitle:@"item 1"]; 
     [headerCell addItemWithTitle:@"item 2"]; 
     [headerCell addItemWithTitle:@"item 3"]; 

     NSTableColumn *column; 
     [column setHeaderCell:headerCell]; 
     [column sizeToFit]; 

     [_tableView addTableColumn:column]; 
    } 

    /* If we don't do this we get a final (space filling) column with an unclickable (dummy) header */ 
    [_tableView sizeLastColumnToFit]; 

} 

유사한 AppDelegate에 -awakeFromNib 나에 모든 것을 함께 묶을 수있다.

마치 복제 된 마지막 셀의 이미지 인 것 같습니다. 그래서 나는 빈 이름으로 테이블 뷰에 여분의 열을 추가하고 의도적으로 마우스 클릭을 무시하는 해킹 틱 접근법을 약간 더 많이 사용합니다. 마지막 열의 표시 속성을 설정하여 원하는 모양으로 만들 수 있기를 바랍니다.

이 영역을 제어 할 수있는 NSTableView 또는 NSTableViewDelegate 메서드를 찾을 수 없으므로 다른 솔루션이 매우 복잡 할 수 있습니다. 나도 좋은 해결책에 관심이있을 것이다. 그러나 나는 이것이 당신을 시작하게하기를 바란다!

+0

NSPopUpButtonCell로 좁혀서 문제가 발생했습니다. 표준 NSTableHeaderCell을 사용하는 경우 sizeLastColumnToFit 메서드가 작동하지만 NSPopUpButtonCell을 대신 사용하면 작동하지 않습니다. 이것에 대한 해결 방법이 있는지 확실하지 않은가요? –

+0

위와 같이 NSPopUpButtonCell을 서브 클래스 화해야합니다. –

+0

문제를 해결 한 훌륭한 세부 답변입니다. 비록주의해야 할 사항이 하나 있습니다. - 기본적으로 사용자는 열의 크기를 조정할 수 있으며 마지막 열의 크기를 조정하면 중복 된 머리글 셀이 표시됩니다. 이 시나리오를 피하려면 [tableView setAllowsColumnResizing : NO]를 설정하는 것이 좋습니다. –

0

이 문제가 있으며 NSPopUpButtonCell을 전혀 사용하지 않습니다. 이 홀수 헤더를 숨기는 방법을 다른 방법으로 알려주고 싶습니다. 이 방법을 사용하면 홀수 표 열이 제거되지 않습니다. 즉 '합법적 인'열이 2 개인 경우이 세 번째 열 머리글을 숨기면 두 번째 열과 세 번째 열을 구분할 수 있습니다. 그러나이 경우 모든 열의 크기를 조정하려는 경우에도 중복 헤더가 표시되지 않습니다. 중복 열을 완전히 제거하는 방법과 이것이 발생하는 이유에 대한 해결책이 필요합니다. (그리고 왜이 버그를 고치지 않을 것인가?)

그래서 ...당신은이 헤더가 속한 컬럼의 인덱스를 계산할 수 있으며, 이것에 따라 헤더를 그리거나 그렇지 않습니다. 먼저 하위 클래스 NSTableHeaderCell을 만들고 열의 셀 클래스로 설정합니다. 하자가 서브 클래스는 TableHeaderCell라는 가정

for column in self.tableView.tableColumns { 
    let col:NSTableColumn = column as! NSTableColumn 
    //you can operate with header cells even for view-based tableView's 
    //although the documentation says otherwise. 
    col.headerCell = TableHeaderCell(textCell: col.title) 
    //or what initialiser you will have 
} 

그런 다음 TableHeaderCell의 drawWithFrame 방법이 있어야한다 : 당신이 중복 헤더 그린하지 않습니다이 후

override func drawWithFrame(cellFrame: NSRect, inView controlView: NSView) { 
    let headerView = controlView as! HashTableHeaderView 
    let columnIndex = headerView.columnAtPoint(cellFrame.origin) 
    if columnIndex == -1 { 
     return 
    } 

    //parent's drawWithFrame or your own draw logic: 
    super.drawWithFrame(cellFrame, inView: controlView) 
} 

을가되지 않은 열 및 columnAtPoint 방법에 속하기 때문에 -1을 리턴합니다.