Est ce possible de "sous sous classer" une classe déjà sous classée
Fred20
Membre
Bonjour
Ma question va peut être paraitre bête mais je cale sur un souci.
J'ai actuellement un QTMovieView que j'ai sous classé pour pouvoir utiliser les doubles clicks à des fins spécifiques (récupérer le currentTime au moment du double clic). J'ai fait en parallèle une application pour dessiner des traits sur une NSView. J'aimerais maintenant utiliser cette 2e application sous forme de classe afin de pouvoir dessiner des traits sur ma video. Je pensais sous classer ma QTMovieView avec cette classe mais elle est déjà sous classéey pour utiliser le double click.
Du coup comment dois je faire pour utiliser ma classe de dessin (donc les mouseDown, drawRect ...) dans ma classe QTMovieView (qui j'utilise déjà le mouseDown mais pour le double click) ?
Merci d'avance
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Bonjour,
Je ne sais pas si ça va t'aider, mais j'ai déjà fait quelque chose du genre, mais j'en suis venu plutôt à utiliser les layer d'une vue perso.
=> sous-classe de NSView (tu gères tes clicks et tes clacks)
=> Tu ajoutes un layer pour dessiner "tes traits" (cf doc CALayer : j'avais utilisé un delegate pour le dessin)
=> Tu ajoutes un QTMovieLayer.
Du coup, tu as une sous-classe de NSView qui te permets de répondre aux événements, et des layers qui permettent l'affichage de la vidéos et des "décorations"...
C'est ainsi que j'avais fait une petite appli pour l'étude du mouvement d'un mobile : on pointe à la souris les positions successives d'un objet, et on en déduit la vitesse, l'accélération ... Après, tu peux sûrement faire autrement, mais sous-classer QTMovieView, pas sûr du résultat.
Contrairement à d'autres langages, Objective-C ne permet pas l'héritage multiple, c'est à dire hériter de plusieurs parents à la fois. (Je ne vais pas discuter des raisons, mais c'est plutôt sage comme approche).
De fait, il faut aller dans le sens du langage: préférer la composition à l'héritage. Aussi la méthode de Mick est elle bonne: dessiner avec une autre classe. Mick te propose d'utiliser une CALayer, mais tu peux aussi ajouter une NSView en subview à QTMovieView.
Comme l'a dit Céroce, tu utilise la composition. Cet à dire que si ta classe de déssin se nomme NSViewDraw, tu crée une property du style nSViewDrawObject : NSViewDraw et dans ta méthode mouseDown() de ta classe QTMovieView tu appel [nSViewDrawObject
mouseDown] par exemple. Ainsi mouseDown de chaque classe est appelé.
Merci à tous de vos réponses. Je vais essayer tout ça. Bon ça va me prendre un peu de temps car je ne connais pas bien CALayer mais je vous tiens au courant de mes résultats
Bon je viens d'essayer les 2 solutions (layer et view) mais pour l'instant de façon très simple : à partir de ma MSView, je rajoute une autre NSView. Voici le code (en commentaire la partie layer):
Les soucis : (1) dans le cas des layer (mais pas dans addView), je n'accède plus au drawRect de ma 1ere vue (le fond devait être dessiné en bleu, ce qui n'est plus le cas et je n'y passe plus dans le débugger), et (2), ma 2e vue reste au 1er plan et je n'arrive pas à la mettre en fond.
Comment modifier cela ?
Merci d'avance
Vaste sujet que Core Animation... Quelques pistes:
- Le moment où on appelle -setWantsLayer: importe, regarde la doc. Il y a deux modes (layer-hosting, layer-backed), et dans ton exemple, tu es en layer-hosting.
- En mode layer-hosting, la vue héberge la layer, et donc ne se dessine plus dans -drawRect:. C'est maintenant la layer qui doit se dessiner.
Pour dessiner une layer, il y a deux choix possibles:
- hériter de CALayer et surcharger -renderInContext:
- ou dessiner dans la méthode -drawLayer:inContext: de CALayerDelegate
Je te conseille cette seconde approche, plus centralisée; n'oublie pas de mettre la vue en déléguée de sa layer.
oui comme tu dis, vaste sujet le CA...
Bon, je crois comprendre les pistes. Je vais les tester.
Merci Céroce. Je reposterai quand j'aurai avancé
ok, j'ai testé le drawLayer: inContext et je pense avoir compris le fonctionnement. En fait, si j'ai bien compris, il dessine une layer puis une autre et ainsi de suite. Dans mon cas, j'ai 2 layers : voici le code
et voici le code du draw layer :
LE souci, c'est que je ne dessine que le rectangle rouge (celui de uneAutreVue) mais je ne passe jamais dans l'autre qui doit être en bleu en dessus (celui du self)
Je suppose que j'ai oublié quelque chose mais je ne sais pas quoi
Merci de votre patience
En fait, il existe plusieurs layer associées (model layer, representation layer). Il faut juste dessiner dans la layer passée en argument. Je précise qu'il ne s'agit pas de la layer d'une autre vue: elle concerne bien ta vue.
Justement, je pensais avoir créé 2 layera : celle de ma vue principale (self) et une autre que j'ai ajouté (uneAutreVue). Du coup, en faisant un display sur une layer puis sur l'autre je devais passer dans le bon layer sous drawLayer et donc dessiner le carré rouge puis vert. Or, je ne passe jamais dans if(layer == self.layer) (dans drawLayer).
Pourquoi ??
if([layer isEqualToObject: self.layer]) ?
isEqualToObject ne semble pas exister. J'ai donc essayé avec isEqualTo mais pas mieux
OK, je n'avais pas compris le problème, mais tu as entièrement raison.
Pour le pourquoi, c'est à cause de ce que je t'explique plus haut: tu as une Model layer et une Representation layer.
Maintenant, pour ce qui est de la solution, j'en vois deux:
- utiliser la vue parente en mode layer-backed plutôt que layer-hosting, et dessiner dans -drawRect: comme avant.
- ou sous-classer CALayer et dessiner dans -drawInContext pour être sûr de la classe de la layer.
Merci beaucoup Céroce
Ceci dit : 2 choses
- comment passe-t-on en mode layer-backed ? le Core Animation comment réellement à m'intéresser à force de fouiner !!
- entre temps, j'ai touvé une autre solution à mon problème initiale qui consiste à travailler non pas sur les layer mais sur les vues en donnant la possibilité de cliquer au travers des vues dans les zones transparentes. Voici le code :
Cependant, Céroce, si tu peux me donner cette info (mode layer-backed) que je progresse ds ce domaine
Merci à toi et à tous
Dans l'attente de cette réponse
Je te l'ai dit, il faut lire la doc concernant -setWantsLayer: ;-)
En gros, il faut juste que tu n'écrives pas self.layer = [CALayer layer];
Dans ce cas, la layer sera créée quand setWantsLayer: est appelée, et mise à jour lors des appels à -drawRect:.
Grosse confusion de ma part
Dans la doc, j'avais compris qu'il fallait automatiquement les 2 ... bon, j'ai progressé en anglais depuis le début mais j'ai encore beaucoup de lacunes ::)
Merci encore Céroce