[NSButton Subclass] Gérer le mouvement de la souris

novembre 2008 modifié dans Objective-C, Swift, C, C++ #1
Salut à  tous,

Pour ceux qui s'aventurent un jour dans la réalisation de NSButton personnalisés (HUD par exemple), voici un code bien pratique qui permet de surveiller la position de la souris afin de changer l'état (Appuyé ou non) du bouton.

Par exemple, si vous appuyez sur un NSButton basique et qu'en restant appuyé vous sortez de sa zone, vous pouvez relâcher votre souris sans que le click soit effectué.

<br />- (void)mouseDragged:(NSEvent*)theEvent<br />{<br />	if(![self isEnabled])<br />		return;<br />	<br />	NSPoint location = [theEvent locationInWindow];<br />	<br />	location = [[[self window] contentView] convertPoint:location toView:[self superview]]; <br />		<br />	if(location.x&lt;[self frame].origin.x){<br />		performClick = NO;<br />		[self mouseUp:nil];<br />	}else if(location.x&gt;[self frame].origin.x+[self frame].size.width){<br />		performClick = NO;<br />		[self mouseUp:nil];<br />	}else if(location.y&lt;[self frame].origin.y){<br />		performClick = NO;<br />		[self mouseUp:nil];<br />	}else if(location.y&gt;[self frame].origin.y+[self frame].size.height){<br />		performClick = NO;<br />		[self mouseUp:nil];<br />	}<br /><br />}<br />


Pourquoi la conversion ?

- Si votre bouton se trouve directement dans votre fenêtre, le "NSPoint location = [theEvent locationInWindow];" suffit.
Sauf que si votre bouton se trouve dans une vue, qui est elle même implantée dans votre fenêtre, ça change complètement l'origine de votre bouton qui est calculé en fonction de sa position dans la vue et non pas dans la fenêtre.

Le BOOL "performClick" permet simplement à  la méthode "mouseUp" (que j'utilise habituellement pour envoyer l'action du bouton avec [self performClick:self]; )  de savoir oui ou non si l'action du bouton doit être réalisée ou non.
Voili voilu :)

Réponses

  • AliGatorAliGator Membre, Modérateur
    20:45 modifié #2
    Heu j'ai jamais essayé de sous-classer NSButton, mais c'est pas le genre de truc déjà  géré automatiquement ? Genre avec les méthodes hitTest: ou truc comme ça, et avec les NSActionCells (dont dérive NSButtonCell) ?

    Je veux dire moi si je voulais faire un bouton au look personnalisé, pour pas perdre les fonctionnalités propres au bouton, avec la gestion des target/actions, et tout, j'aurais juste sous-classé NSButtonCell, non ? et demandé à  mes boutons d'utiliser cette cellClass à  la place de celle par défaut ? Et le NSControl qu'est NSButton, lui, gérant juste les interactions et pas le drawing, garderait sa fonction première, dont la gestion des mouseDown:, mouseDragged: et mouseUp: ?
    Ou j'ai loupé un épisode ?

    About Cells and Controls

    Because NSControl uses objects derived from the NSCell class to implement most of its functionality, you can usually implement a unique user interface device by creating a subclass of NSCell rather than NSControl. As an example, let's say you want all your application's NSSliders to have a type of cell other than the generic NSSliderCell. First, you create a subclass of NSCell, NSActionCell, or NSSliderCell. (Let's call it MyCellSubclass.) Then, you can simply invoke NSSlider's setCellClass class method
    If you want to implement your own mouse-tracking or mouse-up behavior, consider overriding startTrackingAt:inView:, continueTracking:at:inView:, and stopTracking:at:inView:mouseIsUp:.


    Après comme j'ai jamais fait y'a sans doute des subtilités que je n'ai pas vues, mais bon, quand même ça reste à  tester et ça vaut le coup de relire cette partie de la doc pour s'assurer qu'on a bien fait les choses proprement et avec la méthode la plus adaptée ;)
  • NoNo Membre
    20:45 modifié #3
    Tout à  fait d'accord avec toi Ali.

    De plus NSButtonCell (et donc ses potentielles sous-classes) a tout ce qu'il faut pour gérer la souris.
    - on peut détecter les survols de la souris sur le bouton (méthodes mouseEntered: et mouseExited:),
    - on peut détecter les évènements souris dans le bouton (startTrackingAt:inView:),
    - on peut suivre les mouvements de la souris pendant un clic (continueTracking:at:inView: , pratique par exemple pour déplacer un bouton sous forme de curseur),

    Et en fin, last but not least, toute la mécanique target/action/delegate reste utilisable.
  • schlumschlum Membre
    20:45 modifié #4
    dans 1226612303:
    Pour ceux qui s'aventurent un jour dans la réalisation de NSButton personnalisés (HUD par exemple), voici un code bien pratique qui permet de surveiller la position de la souris afin de changer l'état (Appuyé ou non) du bouton.

    Par exemple, si vous appuyez sur un NSButton basique et qu'en restant appuyé vous sortez de sa zone, vous pouvez relâcher votre souris sans que le click soit effectué.


    Effectivement, tu t'es pris la tête pour rien... Tout ça est déjà  géré par NSButton / NSButtonCell.
  • 20:45 modifié #5
    OMG j'avais complètement zappé le mouseExited. Youpi :adios!:
    M'en fiche au moins ça m'aurait entraà®né à  me faire chier pour rien ;D j'suis un champion dans ce domaine
Connectez-vous ou Inscrivez-vous pour répondre.