récupérer un event
bofy
Membre
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
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
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
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
- (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...
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:
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:
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 ?
Si tu veux le NSResponder le plus global possible, c'est la contentView de la fenêtre.
• 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:
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.
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.
====================================
#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)
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.
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];
}
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.
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