Problème de mise à jour de NSView

Illuvatar

Membre actif
28 Décembre 2004
148
5
39
J'ai des problèmes assez ennervant avec une NSView.
Je vous décrit brievement le principe. La vue est sensée représenter une grille de 15 sur 15 initialement de couleur uniforme. L'objet possède 3 tableaux d'entiers de 225 cases chacun pour les composantes RVB de chaque case, C1,C2,C3.
J'ai donc un truc dans drawRect: du type :

Bloc de code:
int i;
int j;
NSRect R;

for (i=0;i<=14;i++) {
for (j=1;j<=15;j++) {

[[NSColor colorWithDeviceRed:(float)C1[15*i+j]/100 green:(float)C2[15*i+j]/100 blue:(float)C3[15*i+j]/100 alpha:1.0] set];
R.origin.x=40*i;
R.origin.y=40*(j-1);
R.size.height=40;
R.size.width=40;
[NSBezierPath fillRect:R];
}
}

Je rencontre le probl&#232;me suivant : Il semble que la m&#233;thode d'initialisation ne soit pas appel&#233;e avant d'afficher la vue ( par exemple si je demande &#224; mettre tous les C1 &#224; 100 pendant l'initialisation, la grille n'apparait pas rouge mais noire )
Pour tenter d'y remedier, j'ai cr&#233;&#233; une m&#233;thode externe qui remplit les tableaux Ci et fait un setNeedsDisplay : Tout marche alors mais bon j'aurais aim&#233; que cette &#233;tape se r&#233;alise automatiquement...

Si quelqun a une id&#233;e, j'ai peut-&#234;tre oubli&#233; un truc hyper important ( je suis encore un d&#233;butant en Cocoa )...

Merci d'avance...
 
pour faire les choses proprement, en temps normal, il faudrait dans ta classe View faire la nette distinction entre 3 méthodes fondamentales :

Bloc de code:
-(id)initWithFrame: (NSRect)frameRect;
{
   [super initWithFrame:frameRect]




    return self;
}



Bloc de code:
-(void)drawRect:(NSRect)rect
{


}

C1,C2,C3 déclaré dans l'interface de ta view

Bloc de code:
-(void)awakeFromNib
{



}
cette méthode doit être placé de préférence dans la classe de contrôle de l'application en conformité avec le modèle 3-tiers.


'drawRect' c'est la méthode qui sera appelé à chaque appel de la méthode 'setNeedDisplay' pour forcer de redessiner la zone d'affichage, par conséquent il est inutile de préciser à chaque fois l'initialisation des tailles de rectangle Rect initiale qui peuvent être modifiés quelques lignes plus loin dans 'drawRect'.

sous spotlight tape 'custom view type:pdf' pour accéder à plus d'infos sur la doc fourni avec xcode.

'initWithFrame' permet de spécifier les cadres de tes rectangles : tu donnes les emplacements selon les valeurs de frameRect à des tableaux C1, C2, C3

'awakeFromNib' : tu défnis les valeurs de couleurs que doit contenir tes rectangles, en particulier puisqu'ils sont stockés dans l'interface View tu y accèdes grâce à un IBOutlet:

IBOUTLET NSView *myViewPerso;

dans 'DrawRect', utilise ta méthode 'fill' avec C1,C2,C3

normalement cela devrait être correcte.

par ordre de priorité natif, le programme exécute dans l'ordre suivant :

awakeFromNib
initWithFrame
drawRect
 
Merci beaucoup. En fait j'avais mis mes instructions dans une méthode init: classique qui ne s'appelait jamais puisque les NSView appellent initWithFrame: à leur initialisation ce que j'ignorais ;)...

Enfin maintenant tout marche !

Merci encore je vais tâcher de mieux me renseigner la prochaine fois...
 
J'ai un petit problème qui n'est pas vraiment lié au précedent mais bon c'est dans la continuité et je ne vais pas polluer le forum avec des posts multiples.
En fait j'ai un objet A qui a un outlet vers ma vue personnalisée. Je voudrais que lorsque on clique sur la vue à un endroit précis, l'objet A execute une méthode donnée. Je n'ai aucun problème pour receuillir le NSEvent etc... mais j'ai à priori besoin d'un outlet dans le sens inverse ( de la vue vers l'objet A ). Cependant le compilateur refuse de rajouter un Outlet dans le sens contraire....
Si quelqun a une idée ?
 
ta r&#233;ponse correspond &#224; l'utilisation correcte du mod&#232;le 3-tiers:

Le truc c'est de comprendre correctement la philo de ce mod&#232;le :

3 parties : Mod&#232;le - Controller - View

usuellement :

la section Controller impl&#233;mente les actions (fournirArgent)
la section View impl&#233;mente les &#233;v&#232;nements (mouseClick)

Les &#233;v&#232;nements servent &#224; modifier les sch&#233;mas de configuration des arguments d'une actions. Les actions d&#233;finissent le comportement d'une variable mod&#232;le.

Cliquer sur une cellule de NSButton consiste &#224; valider un sch&#233;ma de configuration d'un mod&#232;le de portefeuille (ie: argent = 500&#8364;) tandis que l'instance du NSButton en question valide l'action 'fournirArgent'. donc au total le mod&#232;le 3-tiers de permet de faire:
fournirArgent( 500 &#8364; , utilisateur1, propri&#233;taire 2); //par exemple


Donc IBOUTlet sert &#224; initialiser et &#224; obtenir les variables mod&#232;les contenus dans un contr&#244;le Cocoa, tandis que les &#233;v&#232;nements impl&#233;ment&#233;s dans un objet View permettent de modifier les contenus de ces variables mod&#232;les durant l'ex&#233;cution du programme.

Donc, si tu utilises un NSButton, cr&#233;e une classe qui contient en d&#233;rivation 'NSButton' et qui impl&#233;mente des m&#233;thodes &#233;v&#232;nements comme 'mouseClick' et relie cette objet &#224; ton contr&#244;le view dans IB dans la section 'custom class', tandis que dans ta classe controller de l'application (d&#233;riv&#233;e traditionnellement soit de 'NSResponder' ou 'NSObject', la tu impl&#233;mentes les 'IBActions' qui r&#233;f&#233;rencent et utilise ton 'IBOUTLET' !

avec un peu de pratique, tu verras &#231;a deviens rapide &#224; faire et clair !

Si tu veux aller un peu plus loin tu utiliseras les notifications !!

dans ta classe contr&#244;ller tu d&#233;finis un objet particulier par exemple 'NSMutableDictionary' si le fait d'utiliser une action en provenance d'une View modifie la valeur d'une clef de ce dictionnaire (par exemple la clef @"Donnateur" ou @"montantMauvaisPayeur" et bien tu signifie par une notification les cons&#233;quences de ce changement de donnateur ou du seuil de la dette atteint lors d'une action effectu&#233; sur ta view !!!
 
Je crois que je vois un peu mieux le truc. Je vais essayer de potasser un peu le sujet.

Merci encore.