drag & drop

tethystethys Membre
08:28 modifié dans API AppKit #1
Bonjour,
je m'intéresse au drop sur une NSView d'une image (venant d'une autre NSView).
La NSView cible a une NSImageView de fond.
Je souhaite positionner mon image glissée à  un endroit précis de ma vue cible, qui représente une partie de la NSImageView.

J'ai deux questions :
1) Pour intégrer la NSImageView et que celle-ci serve d'image de fond, je l'ai superposée avec ma NSView qui implémente le drop, et lui ait appliqué un filtre alpha < 1. Du coup je peux redessiner, sur la NSView, mon image que je glisse quand j'arrive dans ma vue cible, et celle-ci est visible du fait de la transparence de la NSImageView (enfin je suppose).
Y a t'il une autre méthode que d'utiliser ce paramètre alpha ou est-ce la bonne méthode ?
2) Je redessine mon image glissée au bon endroit sur ma NSView lors du concludeDragOperation: je peux la redessiner au bon endroit, mais je souhaiterai le faire uniquement à  une condition: c'est que je sois proche d'un point cible sur la NSView (correspondant à  une zone de la NSImageView comme pour un puzzle),
je suis parti sur un test dans concludeDragOperation basé sur un event positionné dans mouseUp, est-ce une bonne méthode ? est-ce que avoir plusieurs NSImageView correspondant aux differentes zones est une méthode faisable/recommandée aussi ?

Vincent

Réponses

  • CéroceCéroce Membre, Modérateur
    08:28 modifié #2
    Dans l'esprit, la méthode est bonne, parce qu'il ne faut surtout pas essayer de surcharger NSImageView.
    Ta vue perso doit se trouver au dessus de l'image view. ça peut vouloir dire dedans, mais ça peut aussi vouloir dire au même niveau hiérarchique, mais avec un z-order différent (ça se règle dans le xib, mais c'est aussi le cas si ta vue est créée après l'image view).

    Ensuite, certes changer l'alpha de l'image view la rendra translucide, mais ce n'est pas ce que tu veux.
    Dans ta vue:
    - surcharge sa méthode -[isOpaque] pour renvoyer NO.
    - dessine normalement dans sa méthode -[drawRect]. Comme elle est au dessus, le dessin sera superposé.


    Pour la deuxième question, il suffit de déterminer la distance entre le point "cible" et les coordonnées de la souris lors du lâcher. Utilise Pythagore pour le calcul de distance ou la fonction dont je ne me rappelle plus le nom, mais je suis sûr qu'elle existe.


    Utiliser plusieurs image views me parait peu faisable: au mieux, tu peux y glisser des NSImage et les identifier, mais tu sauras juste si le point de la souris se trouve dans l'image view lors du lâcher.
  • tethystethys Membre
    08:28 modifié #3
    dans 1325006961:

    Dans l'esprit, la méthode est bonne, parce qu'il ne faut surtout pas essayer de surcharger NSImageView.
    Ta vue perso doit se trouver au dessus de l'image view. ça peut vouloir dire dedans, mais ça peut aussi vouloir dire au même niveau hiérarchique, mais avec un z-order différent (ça se règle dans le xib, mais c'est aussi le cas si ta vue est créée après l'image view).

    c'est quel menu du xib ? je ne retrouve pas l'appellation z-order, il y a bien un onglet Hidden mais c pour un lien..

    dans 1325006961:


    Ensuite, certes changer l'alpha de l'image view la rendra translucide, mais ce n'est pas ce que tu veux.
    Dans ta vue:
    - surcharge sa méthode -[isOpaque] pour renvoyer NO.
    - dessine normalement dans sa méthode -[drawRect]. Comme elle est au dessus, le dessin sera superposé.


    pour dessiner la vue, je passe par un pointeur sur une NSImage, variable d'instance de ma classe.
    j'utilise drawInRect sur ce pointeur dans drawRect, s'il est non nul, avec un rectangle de la taille de mon image,
    j'ai alloué de la mémoire et l'ai initialisé en dur dans  initWithFrame pour tester, mais malgrè cela j'ai un plantage au bout de trois-quatres drop..
    est-ce que rafraichir la vue au concludeDragOperation peut être à  l'origine du problème ?
    L'allocation et initialisation de mon image dans l'initWithFrame devrait suffire, ou faut-il le faire à  chaque réception de l'evenement drop ?
  • CéroceCéroce Membre, Modérateur
    08:28 modifié #4
    dans 1325113768:

    dans 1325006961:

    mais avec un z-order différent (ça se règle dans le xib, mais c'est aussi le cas si ta vue est créée après l'image view).

    c'est quel menu du xib ? je ne retrouve pas l'appellation z-order, il y a bien un onglet Hidden mais c pour un lien..

    Je viens de vérifier, je me suis trompé, c'est peut-être ainsi sous iOS, bref je ne sais plus. Tu peux changer l'ordre des vues dans la hiérarchie sur la gauche.

    dans 1325113768:

    pour dessiner la vue, je passe par un pointeur sur une NSImage, variable d'instance de ma classe.
    j'utilise drawInRect sur ce pointeur dans drawRect, s'il est non nul, avec un rectangle de la taille de mon image,
    j'ai alloué de la mémoire et l'ai initialisé en dur dans  initWithFrame pour tester, mais malgrè cela j'ai un plantage au bout de trois-quatres drop..
    est-ce que rafraichir la vue au concludeDragOperation peut être à  l'origine du problème ?
    L'allocation et initialisation de mon image dans l'initWithFrame devrait suffire, ou faut-il le faire à  chaque réception de l'evenement drop ?

    Conserver une référence vers la NSImage ne suffit pas, il faut la retenir. Autrement, si la classe qui conserve la NSImage en variable d'instance est désallouée, elle désallouera sa NSImage.
  • tethystethys Membre
    08:28 modifié #5
    dans 1325141348:


    Conserver une référence vers la NSImage ne suffit pas, il faut la retenir. Autrement, si la classe qui conserve la NSImage en variable d'instance est désallouée, elle désallouera sa NSImage.


    mais pourtant mon instance de NSView est créee au démarrage de l'appli et fermée à  la fermeture, non ?
    je n'ai qu'une seule instance de cette classe.

    de plus, je la retiens dans le setImage (cf ci dessous)
    <br />	[newImage retain];<br />	[image release];<br />	image = newImage;<br />	<br />	[self setNeedsDisplay:YES];<br />
    

    et je fais ce setImage quand je lis son nom dans le presse-papiers, dans performDragOperation (en pasant par une NSImage intermédiaire que j'alloue et init et release après le setImage)
    qu'est-ce que je fais de travers ?
  • tethystethys Membre
    08:28 modifié #6
    dans 1325168588:


    et je fais ce setImage quand je lis son nom dans le presse-papiers, dans performDragOperation (en pasant par une NSImage intermédiaire que j'alloue et init et release après le setImage)
    qu'est-ce que je fais de travers ?


    ok, en fait l'erreur était de passer par une image intermediaire en plus, il suffit d'affecter sa nouvelle valeur et de faire un retain quand je lit dans le presse-papiers.
    merci Céroce !
    mais ceci-dis, on ne crée pas une nouvelle référence à  image, on ne fait que modifier sa valeur, non ?
  • CéroceCéroce Membre, Modérateur
    08:28 modifié #7
    Je ne comprends pas trop ta question, mais "retain" ne crée pas une nouvelle instance de l'image. Les pointeurs dans les deux cas auront la même valeur puisqu'ils pointent sur le même objet.
  • tethystethys Membre
    08:28 modifié #8
    dans 1325173217:

    Je ne comprends pas trop ta question, mais "retain" ne crée pas une nouvelle instance de l'image. Les pointeurs dans les deux cas auront la même valeur puisqu'ils pointent sur le même objet.

    bah en fait ma remarque c'est que l'image n'est pas désallouée tant que la vue n'est pas fermée,
    donc la modification de sa valeur avec [NSImage imageNamed:value] quand je lis le presse-papiers reviendrait à  créer une référence sur cet objet ?? je vois mal là .. l'objet à  déjà  été crée avec alloc init dans intiWithFrame, on ne fait que modifier sa valeur et ce vers quoi il pointe..

    sinon pour une vue cible qui est une classe différente de la vue source (j'ai fait deux classes pour bien comprendre les méthodes utilisées par chaque action), le mouseUp appelé quand on relache l'objet sur la vue cible devrait être celui de la vue cible, non ?
    parce que là  aucun des deux n'est appelé.
  • CéroceCéroce Membre, Modérateur
    décembre 2011 modifié #9
    Là , je comprends encore moins. +[NSImage imageNamed:] attend le nom d'un fichier image qui se trouve dans les ressources...

    Pour le -[mouseUp:], je ne sais pas trop. De mémoire, il n'est émis que si le -[mouseDown:] a eu lieu dans la même vue, ce qui expliquerait ce que tu observes.
    De toute façon, les clics n'interviennent pas dans la gestion du glisser-déposer, tes vues devant se conformer respectivement aux protocoles NSDraggingSource et NSDraggingDestination (voir le guide d'Apple pour plus d'infos).
  • tethystethys Membre
    08:28 modifié #10
    dans 1325180185:


    De toute façon, les clics n'interviennent pas dans la gestion du glisser-déposer, tes vues devant se conformer respectivement aux protocoles NSDraggingSource et NSDraggingDestination (voir le guide d'Apple pour plus d'infos).

    Je comptais utiliser les clics pour avoir les coordonnées du point où on relache la souris.
    mais j'ai trouvé la méthode de classe suivante :
    <br />[NSEvent mouseLocation]<br />
    

    'regardless of the current event or pending events' d'après la doc.
    à  quel événement est-ce que ça s'applique si je l'appelle dans une fonction qui "n'utilise" pas d'événement en paramètre ?

    en le testant je m'aperçois que dans une zone donnée, ça ne retourne pas toujours une valeur cohérente (test fait sur mouseDown, en cliquant ailleurs de la zone puis en revenant)

    Il me semble que pour ce genre de raison il est plus judicieux de travailler sur une même classe comme NSView cible et source, non ?
  • mpergandmpergand Membre
    08:28 modifié #11
    mouseLocation retourne la position de la souris en coordonnées de l'écran.
    Tu as aussi mouseLocationOutsideOfEventStream de NSWindow qui te donnes la position dans la fenêtre.
  • tethystethys Membre
    08:28 modifié #12
    dans 1325199191:

    mouseLocation retourne la position de la souris en coordonnées de l'écran.
    Tu as aussi mouseLocationOutsideOfEventStream de NSWindow qui te donnes la position dans la fenêtre.

    oui, j'ai vu ça dans la doc,
    mais comment expliquer que la valeur, pour la méthode mouseLocation, ne soit pas - grosso modo - la même quand on clique dans la même zone (j'avais des differences de valeur: 200 à  800 après avoir cliqué en dehors de la zone...)
  • CéroceCéroce Membre, Modérateur
    08:28 modifié #13
    Dans le protocole NSDraggingInfo, il y a une méthode -draggingLocation. Si je ne trompe pas, il doit s'agir du point de destination, exprimé en coordonnées fenêtre.
    Convertit le point avec -[NSView convertPoint:fromView:] en passant [tt]nil[/tt] pour view.
  • tethystethys Membre
    08:28 modifié #14
    super cette méthode, ça marche nickel !
    merci de ton aide
Connectez-vous ou Inscrivez-vous pour répondre.