bounds ou frame ? et passage de clic

AliGatorAliGator Membre, Modérateur
août 2005 modifié dans API AppKit #1
Hello all,

Première question : j'ai du mal à  capter la différence entre bounds et frame...
J'ai compris dans la doc que la frame c'était la position et la taille de mon NSControl dans la superview, et que bounds c'était sa position et taille dans le système de coordonnées de l'objet lui-même...
Exemple, j'ai dans IB une fenêtre et j'ai placé dedans une NSView de 100x200 en position 10x20
sa frame sera alors de (10,20,100,200), et ses bounds de (0,0,100,200), c'est ça ?

Mais alors :
- y'a des fois où l'origine des bounds n'est pas (0,0) ?
J'ai essayé de faire mumuse avec setBoundsOrigin: d'une NSView et voir ce que ça faisait, d'après la doc j'ai cru capter que ça s'arrangeais pour mettre l'origine des bounds sur l'origine du repère local, mais bon j'ai du mal à  visualiser ça.
- y'a des fois où la taille (largeur/hauteur) de la frame et des bounds n'est pas la même ?
Pareil j'ai essayé ça aussi, mais je vois pas l'intérêt de réduire les bounds d'une NSView sans réduire sa frame à  la même taille...

Autre sujet que je met dans la même question :
De plus, comme je l'ai expliqué dans d'autres posts, j'ai une sous-classe de NSView qui contient une NSMatrix comme unique subView (créée par code). Je voudrais que quand on clique dans la matrice le clic soit bien passé à  la NSMatrix (ça c'est déjà  le cas de façon automatique, encore heureux), mais que quand on clique hors de la NSMatrix (dans une zone de ma NSView où y'a rien de dessiné, en fait, ni de subView), que ça passe le clic à  l'objet d'en dessous.

J'aurais bien surchargé mouseDown: de ma NSView mais je pense pas que ce soit la solution et puis faudrait le faire pour mouseUp et tous les autres events de souris, donc c'est pas comme ça qu'il faut faire ;)
J'ai essayé un peu aussi de surcharger hitTest: comme ça
(NSView*)hitTest:(NSPoint)pt<br />{<br />	NSView* deepestView = [super hitTest:pt];<br />	if (deepestView == self)<br />		return nil; // c&#39;est là  que je sais pas quoi mettre pour passer au suivant<br />	else<br />		return deepestView;<br />}
Mais ça marche pas mieux (ça doit pouvoir "cacher les events de souris aux subview" comme le dit la doc, mais pour au contraire les laisser "passer à  travers", là ...?)

Ensuite je me suis demandé si les nextResponders & co n'avaient pas qqch à  voir là  dedans, mais ne maitrisant pas le sujet, j'en suis pas trop trop sûr...? (un tuto ?)

Et c'est là  que j'ai regardé du côté de bounds en pensant que la différence avec frame était peut-être que bounds = la zone cliquable... (Et heu en fait ça n'a pas l'air... :))

---

Bref, je patauge un peu sur ces 2 points (p'tet bien liés, p'tet pô). Comment rendre une zone d'une NSView "transparente au clics" pour que les events de souris "passent à  travers la vue" et soient passés au NSControl se trouvant en dessous ?
(et puis c'est quoi cette notion différente entre bounds et frame ?)

Merchi !! :o

Réponses

  • 17:29 modifié #2
    La subview est 'au dessus' de la superview pour les événements de la souris. Donc si tu surcharges le mouseDown & co, la matrix ne sera pas affectée par cette surcharge de code et fonctionnera normalement.

    N'oublie pas non plus que les event de type mouseDown ne sont pas en coordonnées de la vue, mais en coordonées de la fenêtre. La conversion se fait comme ça:
    [tt]- (void)mouseDown:(NSEvent *)event {
    NSPoint point = [event locationInWindow];
    point = [self convertPoint:point toView:nil];
    NSLog(@Down:%@",NSStringFromPoint(point));

    }[/tt]

    Sinon pour frame/bounds, je ne sais pas si tu as connaissance de cette page:
    http://developer.apple.com/documentation/Cocoa/Conceptual/DrawViews/index.html
  • fouffouf Membre
    17:29 modifié #3
    Origine des bounds :
    Oui, ya des fois où c'est pas 0,0. Perso, j'utilise cette fonction avec translateBoundsOriginToPoint: (ou un truc comme ca). Pour les programmes de Maths ou de dessin par exemple, ca peut-être très utili de mettre l'origine dans un endroit qui n'est pas un coin ;)
    (Je dois très HS la :P)
  • AliGatorAliGator Membre, Modérateur
    17:29 modifié #4
    dans 1124447234:

    La subview est 'au dessus' de la superview pour les événements de la souris. Donc si tu surcharges le mouseDown & co, la matrix ne sera pas affectée par cette surcharge de code et fonctionnera normalement.

    N'oublie pas non plus que les event de type mouseDown ne sont pas en coordonnées de la vue, mais en coordonées de la fenêtre. La conversion se fait comme ça:
    [tt]- (void)mouseDown:(NSEvent *)event {
    NSPoint point = [event locationInWindow];
    point = [self convertPoint:point toView:nil];
    NSLog(@Down:%@",NSStringFromPoint(point));

    }[/tt]
    Ok mais alors y'a un truc bizarre : vu ce que tu me dis, normalement je n'ai donc rien à  faire puisque l'implémentation par défaut des events mouse c'est de le faire passer au nextResponder... donc normalement le clic souris "passe déjà  à  travers" ma NSView, puisque le clic est transmis aux "éléments en dessous".
    Pourtant dans IB j'ai mis un NSButton sous ma vue (je l'ai bien mis en dessous, pas en tant que subView, je l'ai d'ailleurs mis à  cheval sur la vue). Si je clique sur ce bouton, le clic n'est pris en compte que s'il est hors de la NSView. Donc ma NSView fait "écran" pour mon clic et ne le passe pas au NSButton alors que c'est ce que je souhaiterai...

    Ceci dit je vois d'ici la réponse : mettre un bouton à  cheval sur une NSView c'est pas malin, soit tu le mets en dessous et alors c'est logique que ça prenne pas le clic (du moins tant que la NSView est pas hidden), soit tu le mets dans la NSView, et là  ce sera une subview et le clic sera pris en compte tout seul... Mouais... bon... ben je sens que ça va rester comme ça alors :p
    dans 1124447234:
    Sinon pour frame/bounds, je ne sais pas si tu as connaissance de cette page:
    http://developer.apple.com/documentation/Cocoa/Conceptual/DrawViews/index.html
    Ouaip j'avais déjà  commencé à  regarder une autre page de la doc Apple mais je n'avais pas trouvé de cas présenté où les bounds n'ont pas leur origine à  (0,0) ou des cas où les bounds n'ont pas la même taille (LxH) que la frame. Je vais éplucher ton lien pour voir.
    Thanks.
  • 17:29 modifié #5
    dans 1124455409:

    Ok mais alors y'a un truc bizarre : vu ce que tu me dis, normalement je n'ai donc rien à  faire puisque l'implémentation par défaut des events mouse c'est de le faire passer au nextResponder... donc normalement le clic souris "passe déjà  à  travers" ma NSView, puisque le clic est transmis aux "éléments en dessous".
    Pourtant dans IB j'ai mis un NSButton sous ma vue (je l'ai bien mis en dessous, pas en tant que subView, je l'ai d'ailleurs mis à  cheval sur la vue). Si je clique sur ce bouton, le clic n'est pris en compte que s'il est hors de la NSView. Donc ma NSView fait "écran" pour mon clic et ne le passe pas au NSButton alors que c'est ce que je souhaiterai...


    Le nextResponder, c'est si jamais tu navigues entre les contrôles au clavier avec la touche tab, donc rien à  voir avec la souris.

    Ce que tu expliques avec le bouton ne rentre pas en contradiction avec ce que j'ai dit. Ta vue étant au dessus, elle prend le mouseResponder, donc le bouton ne l'a pas. Mais tu as visiblement mal compris: la superview est sous la subview, donc si on clique sur une subview, c'est elle qui prend le firstResponder. Donc ta NSMatrix a priorité sur la vue parent, le click ne passe jamais à  traver la NSView, vu qu'il ne l'atteint jamais.
  • AliGatorAliGator Membre, Modérateur
    17:29 modifié #6
    Si si si j'ai bien compris, mais j'ai p'tet mal expliqué. Une image fera mieux l'affaire : cf ci-dessous.
    La matrix c'est en gris, avec les cells dedans.
    LA NSView c'est le tout, avec les zones bleues qui apaprtiennent à  la NSView mais pas à  la NSMatrix.
    NSMatrix est une subView de ma NSView, qui a ici exactement la même largeur, mais qui est moins haute.

    Quand je clique en plein milieu de ma NSView, ma NSMatrix (qui est un subView de cette NSView) reçoit l'event de clic, ça pas de souci. Et c'est normal, puisque comme tu le dis si bien, les subViews (ici la matrix) se trouvent "au dessus" de leur superView.
    Mais quand je clique dans les zones bleues, qui appartiennent à  ma superView (NSView) mais pas à  ma NSMatrix qui est dedans, je voudrais que le clic soit transmis en dessous... en particulier à  mon NSButton que j'ai mis à  cheval...

    En effet ma NSView ne me sert que de "conteneur" de ma NSMatrix pour la centrer et la positionner comme il faut facilement, mais dans les zones bleues y'a rien de dessiné et pour l'utilisateur qui lance mon appli c'est comme s'il n'y avait rien du tout...donc il va pas comprendre s'il peut pas cliquer sur mon NSButton !

    Je sais pas si c'est plus clair comme ça ? En gros si la NSView reçoit un clic (même pas besoin de vérifier si ce clic est sur la NSMatrix ou pas puisque si c'est le cas la NSView ne recevra pas l'event, les superView étant au dessus des subView, tu vois que j'ai compris :)), alors l'ignorer et le laisser "passer à  travers".
    D'après la doc apple l'implémentation par défaut de mouseDown: de NSResponder ne fait que passer au nextResponder, donc ça devrait cliquer sur le bouton même s'il est en dessous de la NSView comme ici... pourtant... :(

    [Fichier joint supprimé par l'administrateur]
  • AntilogAntilog Membre
    17:29 modifié #7
    Probablement une question bête, mais je dois la poser  :o

    Pourqu'oi ne pas passer le bouton au dessus de tout???
  • AliGatorAliGator Membre, Modérateur
    17:29 modifié #8
    dans 1124461740:

    Probablement une question bête, mais je dois la poser  :o

    Pourqu'oi ne pas passer le bouton au dessus de tout???
    Méheuuu !
    Passkeu !!! :)

    Non en fait ça a 2 buts :
    1) Me permettre de capter comment les events souris sont gérés, comment ça marche et comment passer l'event à  une vue en dessous (donc à  titre pédagogique)
    2) Proprement implémenter ma classe. En effet qui me dit que, une fois ma classe bien écrite, je ne la réutiliserai pas dans un autre projet ? Et en particulier si jamais dans cet autre projet je crée ma squareBoard (c'est le nom de ma classe dérivée de NSView et contenant ma NSMatrix) par le code, et que je la positionne par le code, j'aimerais ne pas avoir à  me soucier des cas où il y a un bouton en dessous ou pas.

    Bon je vous l'accord, la question reste un peu stupide puisque le but de la classe étant que la matrice soit proprement dimensionnée et reste carrée, mais se redimentionne toute seule quand la NSView est redimensionnée (ce qui me permet d'utiliser les "ressorts" dans IB pour le positionnement)... donc vu l'utilisation, j'ai aucun intérêt à  mettre un bouton à  cet endroit puisque si ma fenêtre est redimentionnée (élargie) ma vue le sera aussi, et ma matrice va augmenter en taille pour suivre... les zones bleues vont du coup diminuer... et le bouton va finir par être cachée par la matrice ;)

    Mais bon, ça m'empêche pas de perséverer pour comprendre comment faudrait faire ! Et puis si un jour je veux implémenter ce comportement pour un tout autre contexte...

    A des fins didactiques, on vous dit !
    :) :) :) :)

    (Moi, perfectionniste ? noooannnn....)
  • Eddy58Eddy58 Membre
    17:29 modifié #9
    dans 1124463437:

    2) Proprement implémenter ma classe. En effet qui me dit que, une fois ma classe bien écrite, je ne la réutiliserai pas dans un autre projet ? Et en particulier si jamais dans cet autre projet je crée ma squareBoard (c'est le nom de ma classe dérivée de NSView et contenant ma NSMatrix) par le code, et que je la positionne par le code, j'aimerais ne pas avoir à  me soucier des cas où il y a un bouton en dessous ou pas.

    A des fins didactiques, oui c'est utile, mais d'un côté conceptuel, ça révèlerait un problème d'avoir des boutons ou autres contrôles planqués sous une view...::)
  • 17:29 modifié #10
    Chuuuuuuuut, surtout pas perturber AliGator quand il pose des questions. Laisse faire, et surtout réponds. Et dans un an, on pourra mettre tous ces posts l'un à  la suite de l'autre (enfin, pas immédiatement, il faut qu'il apprenne encore un peu) et on pourra en faire un bouquin.
  • Eddy58Eddy58 Membre
    17:29 modifié #11
    Ha oui, et comment appelleront nous ce bouquin alors ?? ???
    J'ai une idée : "O2C2 - Le guide du voyageur interCocoaà¯ste" ;D
Connectez-vous ou Inscrivez-vous pour répondre.