J'essaie de sous-classe Nsslider pour créer un contrôle appelé numéro de jogging. Fondamentalement, ce dont j'ai besoin, c'est un curseur qui commence toujours au milieu et quand il est déplacé vers la gauche ou la droite, il enverra des notifications de temps en temps (déterminées par un attribut on peut définir) informer son conteneur de sa valeur actuelle, puis lorsque vous Laissez-vous aller du bouton, il retournera au milieu. J'espérais implémenter la fonctionnalité pour renvoyer le curseur au milieu et arrêter l'envoi de notifications dans l'événement MouseUp du curseur, mais il semble que, pour une raison quelconque, Apple désactive l'événement de MouseUp après un événement MouseDown sur le curseur et gère toute la fonctionnalité du curseur. à un niveau inférieur. Est-ce que là-bas, je peux récupérer l'événement de la machine? Si quelqu'un ne peut-il pas suggérer une solution de contournement raisonnable? p>
8 Réponses :
Il y a une astuce que j'utilise (mais n'a pas inventé) pour de telles situations. Tout d'abord, dans IB, désignez le curseur comme «continu», de sorte que vous obtenez des messages d'action car le curseur est déplacé. Ensuite, dans la méthode d'action, procédez comme suit:
[NSObject cancelPreviousPerformRequestsWithTarget: self selector: @selector(finishTrack) object: nil ]; [self performSelector: @selector(finishTrack) withObject: nil afterDelay: 0.0];
Chaque fois que vous remarquez que la mise en œuvre d'une superclasse de Un meilleur moyen de détecter une souris est de sous-classer la cellule et de remplacer la méthode de suivi appropriée. Dans ce cas, vous voulez probablement Mousedragged: code> ou MouseUp: code> n'est pas appelé, il est probablement parce que la mise en œuvre de la classe de Mousedown: code> entre une boucle de suivi. Ceci est certainement vrai de plusieurs sous-classes nscontrol code>, y compris nsslider code>. P>
- (vide) stoptracking: (nspoint) stoppoint At: (nsview *) ControlView Mouseisup: (BOOL) Drapeau CODE>, mais le StartTracking : code> et continuetracking: code> Les variantes peuvent s'avérer utiles pour ce que vous essayez de faire. P>
Il semble que l'idée de Kperryua fournisse la solution la plus propre, donc je vais marquer cela comme la réponse acceptée, mais j'ai fini par utiliser un peu de hack qui a travaillé pour ma situation spécifique, donc je pensais que je pouvais aussi partager cela. p>
L'application que je dois faire une plate-forme transversale afin que j'utilise Cocotron (un projet open source qui implémente une grande partie de l'API de cacao sous Windows) pour atteindre cet objectif et Cocotron ne prend pas en charge la méthode StopTracking: ... mentionné ci-dessus. p>
Heureusement, tout en jouant avec un petit programme de test, nous avons fait découvrir que si vous remplacez la méthode MOUSEDOWN du NSSlider et appelez le super de cette méthode, elle ne revient pas tant que le bouton de la souris n'est pas libéré. Peut simplement mettre le code doit être dans MouseUp à l'intérieur de la méthode MouseDown après l'appel à Super. C'est un peu un hachoir sale, mais il semble être la seule solution qui fonctionnera dans notre cas, nous allons donc devoir y aller. p>
Cela fonctionne pour moi (et est plus facile que le sous-classement NSSlider):
- (IBAction)sizeSliderValueChanged:(id)sender {
NSEvent *event = [[NSApplication sharedApplication] currentEvent];
BOOL startingDrag = event.type == NSLeftMouseDown;
BOOL endingDrag = event.type == NSLeftMouseUp;
BOOL dragging = event.type == NSLeftMouseDragged;
NSAssert(startingDrag || endingDrag || dragging, @"unexpected event type caused slider change: %@", event);
if (startingDrag) {
NSLog(@"slider value started changing");
// do whatever needs to be done when the slider starts changing
}
// do whatever needs to be done for "uncommitted" changes
NSLog(@"slider value: %f", [sender doubleValue]);
if (endingDrag) {
NSLog(@"slider value stopped changing");
// do whatever needs to be done when the slider stops changing
}
}
Cela ne fonctionne pas dans tous les cas (commencez à faire glisser et à passer au menu, vous n'enregistrerez jamais la mise en scène)
Ceci ne peut être effectué que par sous-classement (méthodes telles que de @mprudhom ne fonctionnera pas 100% pour connaître la version)
Pour le début de la traînée, vous devez attraper Pour la fin de glisser, vous devez sousclure Remarque: cette approche rendra votre curseur le premier répondeur, annulant tout autre premier répondeur actuel P> Remarque: Approche de Mprudhom P> devisesfirstreresponder code> (pour Ceci vous devez également fournir également PaniectPaneltObecomekey CODE>) P> MouseDown: code> (son appelé MouseDown, mais elle est appelée Lorsque le bouton est sorti) P> @implementation CustomSlider
- (void)mouseDown:(NSEvent *)theEvent {
[super mouseDown:theEvent];
NSLog(@"OK");
}
- (BOOL)needsPanelToBecomeKey {
[super needsPanelToBecomeKey];
return YES;
}
- (BOOL)becomeFirstResponder {
[super becomeFirstResponder];
NSLog(@"Became first responder.");
return YES;
}
@end
Juste au cas où quelqu'un se demande comment y parvenir à Swift 3 avec un état Nsslider qui est défini sur Continu:
J'avais un besoin similaire, mais pour un curseur sur une barre Nstouch. J'ai utilisé une approche similaire «rapide» comme Marc Prud'hommes et Martin Majewski, juste des événements légèrement différents pour inspecter. Voici le code SWIFT qui vous permet de suivre à la fois la valeur continue et la valeur finale du curseur sur une barre tactile.
func sliderValueChanged(_ sender: NSSlider) {
let doubleValue = sender.doubleValue
Swift.print("Continuous value: \(doubleValue)")
// find out if touch event has ended
let event = NSApplication.shared().currentEvent
if event?.type == NSEventType.directTouch {
if let endedTouches = event?.touches(matching: .ended, in: nil) {
if (endedTouches.count > 0) {
Swift.print("The final value was: \(doubleValue)")
}
}
}
}
Je pense qu'il est préférable de sous-classer le nsslider que d'ajouter du code supplémentaire dans la cible.
Cette méthode transfère les événements complets MouseUp et MouseDown (peut être utile pour obtenir des modificateurs clés) et est prêt à faire face à d'autres Type d'événements si nécessaire. P>
Ce curseur stocke la valeur initiale sur la souris vers le bas, nous pouvons donc obtenir les valeurs initiales et finales de la souris. Ceci est très utile pour des actions ondulables. P>
Cette solution n'atteigna pas les événements de MouseDown si iscontinuous code> est défini sur false code> sur le nslider code>. La solution pour ce cas consiste à appeler le Mousedownosvre code> dans MouseDown (avec:) code> avant d'appeler Super.mousedown (avec:) code> et appelez le < Code> Mousepcyclosure Code> Dans Sendaction (_: à:) code>.