1

J'ai un irritant mineur dans un NSCollectionView dans lequel le NSCollectionViewItem casse visuellement quand je fais défiler la fenêtre.Redessiner NSCollectionView sur le défilement provoque la rupture des graphiques

La vitesse de rupture dépend du taux de défilement. Par exemple, si je défile lentement, la rupture se produit plus souvent. Défilement rapide moins. Il semble que le problème est lorsque le NSView personnalisé du NSCollectionViewItem que j'utilise franchit la limite du cadre visible.

Mon NSView (vue personnalisée du NSCollectionViewItem) a un algorithme de dessin très simple - rien de trop complexe.

Essentiellement, je crée un cadre dans le dirtyRect de la méthode drawRect et créer quelques images à l'intérieur que:

-(void)drawRect:(NSRect)dirtyRect 
{ 
    NSRect mOuterFrame = NSMakeRect(dirtyRect.origin.x, dirtyRect.origin.y, 104, 94); 
    NSRect mSelectedFrame = NSInsetRect(mOuterFrame, 2, 2); 
    NSRect mRedFrame = NSInsetRect(mSelectedFrame, 2, 2); 
    NSRect mInnerFrame = NSInsetRect(mRedFrame, 2, 2); 

    NSBezierPath * mOuterFramePath = [NSBezierPath bezierPathWithRect:mOuterFrame]; 
    NSBezierPath * mSelectedFramePath = [NSBezierPath bezierPathWithRect:mSelectedFrame]; 
    NSBezierPath * mRedFramePath = [NSBezierPath bezierPathWithRect:mRedFrame]; 
    NSBezierPath * mInnerFramePath = [NSBezierPath bezierPathWithRect:mInnerFrame]; 

    [mainBackgroundColor set]; 
    [mOuterFramePath fill]; 

    if (selected) 
     [[NSColor yellowColor] set]; 
    else 
     [mainBackgroundColor set]; 

    [mSelectedFramePath fill]; 

    if (isRedBorder) 
     [[NSColor redColor] set]; 
    else 
     [mainBackgroundColor set]; 

    [mRedFramePath fill]; 

    [[NSColor blackColor] set]; 
    [mInnerFramePath fill]; 
} 

J'ai essayé le verrouillage de la mise au point et la libération avant et après le code, ainsi que la définition des graphiques contexte et le restaurer - aucun d'entre eux semblent résoudre le problème. J'utilise Snow Leopard - pas que je pense que cela fasse une différence.

Solution mise à jour

Pour toute personne intéressée est la solution ici au problème tel que recommandé par NSResponder. Je créais le mOuterFrame initial basé sur les méthodes drawRect:dirtyRect qui, comme indiqué, était la chose incorrecte à faire. Un changement rapide de:

NSRect mOuterFrame = NSMakeRect(dirtyRect.origin.x, dirtyRect.origin.y, 104, 94); 

Pour un 0 basé point d'origine:

NSRect mOuterFrame = NSMakeRect(0, 0, 104, 94); 

J'ai aussi peaufiné l'efficacité du code, être comme je suis en utilisant uniquement des rectangles, comme le suggère bien que le changement de code ci-dessus était suffisant pour résoudre le problème en soi. J'ai dû ajouter un changement pour obtenir une ligne de deux pixels. Nouvelle méthode:

-(void)drawRect:(NSRect)dirtyRect 
{ 
    NSRect mOuterFrame = NSMakeRect(0, 0, 104, 94); 
    NSRect mSelectedFrame = NSInsetRect(mOuterFrame, 2, 2); 
    NSRect mRedFrame = NSInsetRect(mSelectedFrame, 2, 2); 
    NSRect mInnerFrame = NSInsetRect(mRedFrame, 2, 2); 

    [NSBezierPath setDefaultLineWidth:2.0]; 

    [mainBackgroundColor set]; 
    [NSBezierPath strokeRect:mOuterFrame]; 

    if (selected) 
     [[NSColor yellowColor] set]; 
    else 
     [mainBackgroundColor set]; 

    [NSBezierPath strokeRect:mSelectedFrame]; 

    if (isRedBorder) 
     [[NSColor redColor] set]; 
    else 
     [mainBackgroundColor set]; 

    [NSBezierPath strokeRect:mRedFrame]; 

    [[NSColor blackColor] set]; 
    [NSBezierPath strokeRect:mInnerFrame]; 
} 

Répondre

1

La première chose que j'ai remarqué est que votre code ci-dessus est plutôt inutile, puisque vous créez un tas de chemins quand vous pourriez utiliser NSFrameRect() et NSRectFill() au lieu. Deuxièmement, la géométrie de ce que vous dessinez ne doit pas dépendre du rectangle passé à -drawRect :. Ce rectangle vous indique simplement quelle est la zone à mettre à jour, de sorte que vous pouvez être plus efficace pour décider quoi dessiner si votre vue est complexe.

+0

Je pense que vous voulez dire 'NSFrameRect' pas' NSDrawRect'. –

+0

NSResponder - merci. Cela a corrigé le problème (ne basant pas le cadre externe initial sur le dirtyRect). J'ai également modifié le code pour être un peu plus efficace en utilisant NSFrameRect. Merci! – Hooligancat

Questions connexes