Получение дубликата ячейки кнопки заголовка в NSTableView при использовании NSPopUpButtonCell
У меня есть динамический NSTableView, который может добавить количество столбцов в зависимости от предоставленных данных. Для каждого столбца я установил ячейку заголовка NSPopUpButtonCell. (Примечание: мне пришлось использовать пользовательский класс подкласса для NSTableHeaderView, иначе меню не всплыло). Все работает хорошо, кроме дубликата или дополнительной ячейки кнопки заголовка в правом верхнем углу. Он идеально отражает предыдущий выбор столбцов, как показано на скриншотах. Мой вопрос: как мне остановить NSTableView от повторного использования предыдущей всплывающей ячейки заголовка? (Кстати, я пробовал метод setCornerView, но он влияет только на область заголовка над вертикальной полосой прокрутки.)
2 ответа
Я столкнулся с той же проблемой на этой неделе. Я пошел с быстрым решением,
[_tableView sizeLastColumnToFit];
(Однако после обсуждения с OP это требует, чтобы вы использовали подкласс NSPopUpButtonCell в заголовке, а также NSTableHeaderView. Я прилагаю свое решение ниже)
Вы можете к этому, сочетая подходы, изложенные здесь,
Вот упрощенный фрагмент,
// 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
Теперь для подкласса NSTableViewHeader.
//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
Вы можете связать все вместе в AppDelegate -awakeFromNib
или похожие,
-(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];
}
Кроме этого я не понял, как правильно исправить рисунок в этом регионе.
Кажется, что это изображение последней ячейки, которая дублируется. Таким образом, я немного более хакерский подход мог бы добавить дополнительный столбец к вашему табличному представлению с пустым именем, который намеренно игнорирует щелчки мыши. Надеюсь, установив свойства отображения последнего столбца, вы можете заставить его выглядеть так, как вы хотите.
Я не смог найти ни одного метода NSTableView или NSTableViewDelegate, который бы позволял управлять этим регионом, поэтому любое другое решение может быть очень сложным. Мне было бы интересно и хорошее решение, но я надеюсь, что это поможет вам начать!
У меня есть эта проблема, и я вообще не использую NSPopUpButtonCell. Я просто хочу рассказать о другом методе, как скрыть этот нечетный заголовок. Эти методы не удаляют нечетный столбец таблицы, т. Е. Если у вас есть 2 "допустимых" столбца и скрыты этот дополнительный заголовок 3-го столбца, вы все равно сможете перемещать разделитель между 2-м и 3-м столбцом. Но в этом случае вы не увидите избыточного заголовка, даже если вы хотите изменить размер любого столбца. Мне все еще нужно решение, как полностью удалить лишний столбец и почему это происходит. (и почему Apple не исправит эту ошибку?)
Итак... вы можете просто рассчитать индекс столбца, к которому принадлежит этот заголовок, и в соответствии с этим нарисуйте свой заголовок или нет. Во-первых, подкласс 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.