récupérer un event

bofybofy Membre
15:36 modifié dans API AppKit #1
Bonjour

Je pensais qu'il suffisait de faire un
    [truc mouseDown:event];
    mouseLoc = [event locationInWindow];
pour récupérer un clic de souris.

C'est sans doute trop simple, car ça ne marche pas !

Merci de l'aide

Réponses

  • AliGatorAliGator Membre, Modérateur
    15:36 modifié #2
    dans 1209041996:

    Bonjour

    Je pensais qu'il suffisait de faire un
        [truc mouseDown:event];
        mouseLoc = [event locationInWindow];
    pour récupérer un clic de souris.

    C'est sans doute trop simple, car ça ne marche pas !

    Merci de l'aide

    Heu... avec [tt][truc mouseDown:event][/tt] tu sembles vouloir générer un event mouseDown ...?? (sans doute en plus avec event initialisé d'une manière obscure... je vois pas trop la logique de faire toi même l'appel à  mouseDown alors que tu veux récupérer l'event, pas le générer.

    Le truc c'est que Cocoa appelle tout seul le message [tt]-(void)mouseDown:(NSEvent*)event[/tt] d'un NSResponder (NSView, ...) lorsque tu cliques sur ce dernier. Cf la NSResponderChain & co.

    Voir La doc Apple sur les events et entre autres cette page
  • Philippe49Philippe49 Membre
    15:36 modifié #3
    Il faut implémenter
    - (void)mouseDown:(NSEvent *)theEvent;
    dans ta classe, et là  tu récupères par  
       mouseLoc = [event locationInWindow];
  • bofybofy Membre
    15:36 modifié #4
    dans 1209043268:

    Il faut implémenter
    - (void)mouseDown:(NSEvent *)theEvent;
    dans ta classe, et là  tu récupères par 
        mouseLoc = [event locationInWindow];


    Ben, j'ai essayé ça aussi, implémenter (surcharger) mouseDown. Mais visiblement ce n'est pas appelé: un NSLog dans l'implementation ne donne rien.

    Extrait de mon code :

    @interface SecondWindowController : NSObject {
            NSButton * closeButton;
    NSEvent * closeEvent;
    NSPoint mouseLoc;
    IBOutlet NSWindow * secondWindow; // connecté dans IB
    }
    - (void) mouseDown : (NSEvent *) theEvent;



    @implementation SecondWindowController

    - (void) awakeFromNib {

    aFrame = NSMakeRect(200,10,100,30);
    NSLog(@aFrame.button : %.0f : %.0f : %.0f : %.0f, aFrame.origin.x, aFrame.origin.y, aFrame.size.width, aFrame.size.height);
    closeButton = [[NSButton alloc] initWithFrame:aFrame];
    [[secondWindow contentView] addSubview:closeButton];
    [closeButton setTitle:@close ?];
    //

    c'est à  partir de là  que ça se gâte : rien ne marche avec mouseDown !!!
    // comme si les clics n'existaient pas
    [secondWindow mouseDown:closeEvent];
    mouseLoc = [closeEvent locationInWindow];
    NSLog(@mouseLoc : %.0f : %.0f, mouseLoc.x, mouseLoc.y);
    NSLog(@awakeFromNib.out);
    }
    - (void) mouseDown : (NSEvent *) theEvent {
        NSLog(@mouseDown.in);
    }
    @end


    Pour mémoire, j'ai lu autant de doc sur les events (cocoa) et autres que je peux en absorber en 24H...
  • schlumschlum Membre
    15:36 modifié #5
    Ben dans ce cas tu as dû voir que c'est pas sur n'importe quoi qu'est appelé mouseDown, mais sur les NSResponder  ;)
  • 15:36 modifié #6
    La méthode mouseDown est considérée par Cocoa comme une méthode événementielle. Il s'agit d'une méthode qui est invoquée par Cocoa suite aux indications du serveur de fenêtre.
    On ne peut invoquer cette méthode directement. Il faut dans ce cas plutôt construire un événement correspondant au mouseDown. Le prototype de la méthode est la suivante:

    <br />+ (NSEvent *)mouseEventWithType:(NSEventType)type location:(NSPoint)location modifierFlags:(unsigned int)flags timestamp:(NSTimeInterval)time windowNumber:(int)windowNum context:(NSGraphicsContext *)context eventNumber:(int)eventNumber clickCount:(int)clickNumber pressure:(float)pressure;<br />
    


    La création des événements est délicate. A éviter.

    D'autre part, pour exploiter la méthode mouseDown, il faut dériver la classe correspondante, c'est à  dire que tu peux le faire dans les classes NSWindow ou NSButton puisque ton code utilise des instances de ces deux classes.

    Et pour finir, quel est vraiment le but de ton code ? Si tu veux fermer la fenêtre en simulant un clic dans le bouton, il y a plus simple:

    <br />[closeButton performClick:nil];<br />
    

  • bofybofy Membre
    15:36 modifié #7
    Merci XDev

    Bon je vais essayer de me passer des events, bien que je ne comprenne pas pourquoi c'est si compliqué en cocoa

    [closeButton performClick:nil];
    ne fait rien !

    De toute façon je n'ai toujours pas réussi à  obtenir une mouselocation  autre que (0,0).
    Tant que je n'aurai pas les coordonnées du pointeur je serai bloqué.

    Merci

    Autre question : peut-on créer une UI dynamique avec IB ?
  • schlumschlum Membre
    15:36 modifié #8
    Ah mais ça n'a absolument rien de compliqué... Tous les NSResponder répondent à  "mouseDown", et si tu veux récupérer un "mouseDown", il faut travailler avec un NSResponder.
    Si tu veux le NSResponder le plus global possible, c'est la contentView de la fenêtre.
  • 15:36 modifié #9
    Petit réglage

    • Je n'ai jamais dit  que le traitement d'un événement était compliqué. Ce que j'ai dit est que la génération, la construction, d'un événement était compliquée. Ce qui est totalement différent.

    • Je me suis trompé à  propos de la liste des classes qui pouvaient gérer le mieux l'événement mouseDown. Il ne s'agit pas de la classe NSWindow mais de la classe NSView ou dérivée qui est utilisée comme contentView. La contentView est une instance, un objet d'une classe NSView ou dérivée qui s'étend sur l'ensemble de contenu d'une fenêtre, bien que la classe NSWindow soit également capable de gérer cet événement puisqu'elle hérite de NSResponder.

    • Pour que l''instruction performClick fonctionne, il faut que le bouton dispose d'une méthode action. Dans ton cas, il n'en dispose pas. C'est pour cette raison que rien ne se passe. En résumé tu doit implémenter une méthode du type:

    <br />-(IBAction)closeButton_Action:(id)sender<br />{<br />	// Ferme la fenêtre sans effet<br />	[[self secondWindow] close];<br />	// OU avec effet sur la case de fermeture<br />	[[self secondWindow] performClose:nil];<br />} /* closeButton */<br />
    


    Les deux instructions sont exclusives, tu utilises soit la première soit la suivante, mais pas les deux !
    Par ailleurs, il faut effectuer les connections appropriées au niveau d'IB, comme par exemple la target pour l'événement cité plus haut.
  • Philippe49Philippe49 Membre
    avril 2008 modifié #10
    C'est un peu n'importe quoi tout cela.

    Si on veut créer un bouton et le faire agir,

    1) On l'instancie soit dans IB, soit dans le programme (on en a déjà  parlé).

    2) On lui attribue une target , une action soit dans IB par les connections habituelles, soit par programme par :
    [closeButton setTarget:self]; ou [closeButton setTarget:uneInstance];
    [closeButton setAction:@selector(actionDeClose:)]

    3) On implémente -(IBAction)actionDeClose:(id) sender;

    Quand l'utilisateur clique sur le bouton, il déclenche actionDeClose:
    Si on veut le déclencher dans le programme, on fait [self actionDeClose:nil]; self et nil étant adaptables à  la situation ...

    Ce qui fait que je ne vois pas ce que mouseDown: vient faire là -dedans.

  • Philippe49Philippe49 Membre
    15:36 modifié #11
    Et si tu veux que ton contrôleur réponde à  la souris (mais pourquoi faire ?)

    ====================================

    #import <Cocoa/Cocoa.h>
    @interface Controller : NSResponder {
      IBOutlet NSWindow* window;  // connecter dans IB
    }
    @end

    ====================================

    #import "Controller.h"


    @implementation Controller
    -(void) awakeFromNib
    {
       [window   setNextResponder:self];
      // ou [[window contentView] setNextResponder:self];
    }

    -(void) mouseDown:(NSEvent*) theEvent
    {
    NSLog(@Clic On My Face);
    }
    @end


    L'instruction dans awakeFromNib ayant pour effet d'installer l'instance de Controller dans la chaà®ne ascendante des responder (avant ou juste après NSWindow)

    Figure 1-8  Responder chain of a non-document-based application
    (attention c'est un peu différent pour les Document-Based Application)
  • schlumschlum Membre
    15:36 modifié #12
    La "Responder Chain" est valable pour les événements du clavier... Pour les événements de la souris, pas sûr  ???
  • Philippe49Philippe49 Membre
    15:36 modifié #13
    Il faut bien déclarer quelque part le contrôleur dans la chaà®ne de réponse.

    Pour une NSView qui répond à  mouseDown: ce n'est pas nécessaire, elle est naturellement dans la chaà®ne de par le schéma ci-dessus. Mais une simple instance de NSResponder n'a pas de raison d'être prise en compte, (et heureusement) , si elle n'est pas clairement positionnée.

    Ce qui trompe, c'est que pour les key-events, c'est plus compliqué de faire répondre les NSView.
  • Philippe49Philippe49 Membre
    15:36 modifié #14
    Conseils sur NSView (dans event-handling guide)

    If you do not handle the event, pass it on up the responder chain. Although you can directly forward the message to the next responder, it's generally better to forward the message to your superclass. If your superclass doesn't handle the event, it forwards the message to its superclass, and so on, until NSResponder is reached. By default NSResponder passes all event messages up the responder chain. For example, instead of this:
    - (void)mouseDown:(NSEvent *)theEvent {
        // determine if I handle theEvent
        // if not...
        [[self nextResponder] mouseDown:theEvent];
    }

    do this:
    - (void)mouseDown:(NSEvent *)theEvent {
        // determine if I handle theEvent
        // if not...
        [super mouseDown:theEvent];
    }
  • schlumschlum Membre
    avril 2008 modifié #15
    Ce mini-projet bien montre bien comment sont traités les événements...

    En fait, quand on clique sur une vue et qu'elle accepte de devenir firstResponder, que l'ancien firstResponder accept le resign, la nouvelle vue prend le first responder et la gestion des événements, qu'elle peut ensuite déléguer au suivant.

    Donc comme un mouseDown est susceptible de modifier le firstResponder, c'est délicat de parler d'ordre précis pour les événements souris.
  • bofybofy Membre
    15:36 modifié #16
    dans 1209156315:

    C'est un peu n'importe quoi tout cela.

    Si on veut créer un bouton et le faire agir,

    1) On l'instancie soit dans IB, soit dans le programme (on en a déjà  parlé).

    2) On lui attribue une target , une action soit dans IB par les connections habituelles, soit par programme par :
    [closeButton setTarget:self]; ou [closeButton setTarget:uneInstance];
    [closeButton setAction:@selector(actionDeClose:)]

    3) On implémente -(IBAction)actionDeClose:(id) sender;

    Quand l'utilisateur clique sur le bouton, il déclenche actionDeClose:
    Si on veut le déclencher dans le programme, on fait [self actionDeClose:nil]; self et nil étant adaptables à  la situation ...

    Ce qui fait que je ne vois pas ce que mouseDown: vient faire là -dedans.




    Comme toujours quand on a trouvé le truc, ça semble évident.

    Effectivement mouseDown n'est pas vraiment utile... sauf pour moi, parce j'ai appris plein de choses dans cette discussion et ailleurs !

    Merci à  tous
Connectez-vous ou Inscrivez-vous pour répondre.