J'ai un Je dois pouvoir cliquer sur cette affichage dans les sous-espages ci-dessous (de sorte que la vue ci-dessous obtient le statut de premier répondeur), mais tous les événements de la souris sont bloqués sur la vue de dessus (Alpha est Je m'attendais à ce que cela fonctionne, car normalement, cela le fait. Qu'est-ce qui ne va pas? P> nsview code> contenant plusieurs sous-espions. L'une de ces sous-visions est transparente et superposée sur le dessus. P>
1 code>, parce que je dessine des choses debout - il ne devrait donc que cliquer sur des zones transparentes). p>
5 Réponses :
Mettez votre vue transparente dans une fenêtre d'enfant à part entière. P>
Étant donné que la résolution des hits par des portions transparentes de Windows est intrinsèque au gestionnaire de fenêtres. Le travail que vous avez fait ci-dessus n'est pas nécessaire.
Oh, je viens de réaliser qu'il y a en fait une méthode -addchildwindow: code> qui synchronisation des fenêtres! Désolé, je pensais que je devrais faire la synchronisation manuellement alors.
J'ai essayé d'utiliser cette approche, mais il a plus d'inconvénients qui utilisent la solution de contournement code> -FindnextsiblingBeloweventLocation: code>, car la fenêtre n'est pas vraiment liée au Nsview code> et il est donc aussi dessiné quand La vue est invisible et ne fonctionne pas lorsque la vue est par exemple à l'intérieur d'une vue de défilement.
C'est une approche très lourde à un problème trivial
J'ai contourné le problème avec cet extrait de code.
- (NSView *)findNextSiblingBelowEventLocation:(NSEvent *)theEvent {
// Translate the event location to view coordinates
NSPoint location = [theEvent locationInWindow];
NSPoint convertedLocation = [self convertPointFromBase:location];
// Find next view below self
NSArray *siblings = [[self superview] subviews];
NSView *viewBelow = nil;
for (NSView *view in siblings) {
if (view != self) {
NSView *hitView = [view hitTest:convertedLocation];
if (hitView != nil) {
viewBelow = hitView;
}
}
}
return viewBelow;
}
- (void)mouseDown:(NSEvent *)theEvent {
NSView *viewBelow = [self findNextSiblingBelowEventLocation:theEvent];
if (viewBelow) {
[[self window] makeFirstResponder:viewBelow];
}
[super mouseDown:theEvent];
}
Voici une autre approche. Il ne nécessite pas de créer un nouvel objet de fenêtre et est plus simple (et probablement un peu plus efficace) que la méthode ci-dessus.
- (NSView *)hitTest:(NSPoint)aPoint
{
// pass-through events that don't hit one of the visible subviews
for (NSView *subView in [self subviews]) {
if (![subView isHidden] && [subView hitTest:aPoint])
return subView;
}
return nil;
}
Voici une public override func hitTest(_ point: NSPoint) -> NSView? {
// pass-through events that don't hit one of the visible subviews
return subviews.first { subview in
!subview.isHidden && nil != subview.hitTest(point)
}
}
Voici un public override func mouseDown(with event: NSEvent) {
// Translate the event location to view coordinates
let convertedLocation = self.convertFromBacking(event.locationInWindow)
if let viewBelow = self
.superview?
.subviews // Find next view below self
.lazy
.compactMap({ $0.hitTest(convertedLocation) })
.first
{
self.window?.makeFirstResponder(viewBelow)
}
super.mouseDown(with: event)
}
Les vues
-isopaque code> sontno code>