Problemas de redesenho de NSCell
-
11-12-2019 - |
Pergunta
Estou criando um NSCell
subclasse que desenha alguns objetos diretamente na visualização (usando drawInRect:fromRect:operation:fraction:respectFlipped:hints:
) e também desenha um NSButton
instância simplesmente usando o NSView addSubview:
seletor.
Embora todos os objetos desenhados usando o primeiro método sejam desenhados corretamente, estou tendo problemas para desenhar o NSButton
corretamente.A questão é que meu NSButton
as instâncias serão desenhadas nos lugares certos, mas várias vezes.
Pesquisei isso na internet há algum tempo e algumas pessoas sugeriram usar cache, mas não tenho certeza se isso é eficiente.(ir uma matriz contendo botões usando um loop for definitivamente causará uma rolagem lenta, já que exibo muitos dados ...)
Como você faria isso?Estou latindo para a árvore errada?
Este é o código relevante:
- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
NSRect _controlRect = cellFrame;
float _Y = cellFrame.origin.y;
NSRect _accessoryRect = NSMakeRect(_controlRect.size.width - 70.0f, _Y + 9.0f, 50.0f, 23.0f);
_switch = [self _choiceSwitch];
[_switch setFrame:_accessoryRect];
[controlView addSubview:_switch];
}
Solução
Longa história curta: Amigos não deixam amigos addSubview
, enquanto desenha.
Isto é fundamental e não é particularmente bem explicado aspecto do gerenciamento de interfaces de controle, mas é importante enfrentá-lo.
Deixe seus controladores ditarem a "ordem" das subvisualizações, e você pode dormir tranquilo sabendo que esse botão não deve ser abertamente bagunçado (o que NÃO é o caso se ele estiver sendo empurrado dentro de suas rotinas de desenho personalizadas).
É fácil ficar preso neste beco, porque, tipo, ei, eu adicionei um NSImageView
no meu initWithFrame
e tudo parece estar bem… Mas é simplesmente não é como você deveria fazer isso, eu acho… e quando você começa a subclassificar NSControl, etc.é quando você começa a perceber o porquê.
Atualizada: Aqui está um ótimo artigo sobre como projetar controles personalizados com um projeto de amostra igualmente excelente anexado - que incorpora o tipo de organização de código que pode ajudar a evitar esse tipo de problema.Por exemplo..você notará na classe do controlador como ele mantém cada botão separado, único e independente dos negócios de outras visualizações…
for (int butts = 0; butts < 3; butts++) {
NSRect buttFrame = NSMakeRect(0, butts * 10, 69, 10);
ExampleButt *butt = [[ExampleButt alloc]initWithFrame:buttFrame];
[mainView addSubview:butt];
}
Outras dicas
"Desenho" NSButton
adicionar sua instância à hierarquia de visualização cada vez que você desenha a própria célula é definitivamente uma má ideia.Em vez disso, crie um NSButtonCell e configure-o ao seu gosto.Então, em seu -[NSCell drawInteriorWithFrame:inView:]
use um cell ivar para desenhar sua aparência.
Se você quiser ter um clicável NSButton
instância em cada célula da visualização de tabela, tente evitar uma chamada para addSubview:
quando possivel.Cada vez que você fizer isso, a visualização de controle poderá invalidar seu layout e redesenhar tudo do zero, fazendo algum tipo de recursão no seu caso.