2017-09-12 3 views
0

La fenêtre de mon application a une vue éclatée avec trois volets; le volet le plus à gauche héberge une vue hiérarchique basée sur la vue.NSWindow.contentView.hittest() n'atteint pas les sous-vues de NSOutlineView

Lorsque je clique quelque part sur cette vue, je veux déterminer la sous-vue la plus basse dans la hiérarchie sur laquelle j'ai cliqué. C'est-à-dire, quelle rangée, quelle cellule, et finalement quelle sous-vue (contrôle) de la cellule a été cliquée.

J'ai essayé de surcharger mouseDown(with:) sur le contrôleur de vue d'hébergement, mais il n'est pas appelé; Je me suis douté que la vue en plan monopolisait l'événement, donc j'ai décidé de remplacer la méthode directement sur ma sous-classe NSOutlineView elle-même. Cela marche. Cependant, à partir de là, je ne peux pas aller plus loin dans la hiérarchie que le mode plan lui-même:

classe MyOutlineView: NSOutlineView {

override func mouseDown(with event: NSEvent) { 
    if let view = self.window?.contentView?.hitTest(event.locationInWindow) { 
     Swift.print("\(view.className)") 
    } 
} 

... impressions:

MyModule. MyOutlineView

La documentation hittest() lit:

Renvoie le descendantle plus éloigné de la vue dans la vue hiérarchique (y compris lui-même) qui contient un point donné, ou nul si cette se trouve le point complètement en dehors de la vue. Cette méthode est principalement utilisée par un objet NSWindow pour déterminer quelle vue doit recevoir un événement de souris à . Vous auriez rarement besoin d'invoquer cette méthode, mais vous voudrez peut-être la remplacer par pour qu'un objet de vue masque les événements de ses sous-vues. Cette méthode ignore les vues cachées.

Comment puis-je tester les sous-vues les plus élevées de la vue hiérarchique?

Répondre

1

mouseDown(with:) est appelée sur les vues, pas sur les contrôleurs. Habituellement, le contrôle à l'intérieur de la vue de contour gère le mouseDown.

Mais si vous voulez trouver le contrôle, oui, -[NSTableView(NSTableViewRowHeaderSupport) hitTest:] gâcher les choses. Solution de contournement: récupérez la ligne et la colonne, obtenez la vue de la cellule et appelez le hitTest sur la vue des cellules.

override func mouseDown(with event: NSEvent) { 
    let localPoint = self.convert(event.locationInWindow, from: nil) 
    let column = self.column(at: localPoint) 
    let row = self.row(at: localPoint) 
    if column >= 0 && row >= 0 { 
     if let cellView = self.view(atColumn: column, row: row, makeIfNecessary: false) { 
      if let cellSuperViewPoint = cellView.superview?.convert(localPoint, from: self) { 
       if let view = cellView.hitTest(cellSuperViewPoint) { 
        Swift.print("\(view.className)") 
       } 
      } 
     } 
    } 
} 
+0

Merci. Je travaillais sur l'adaptation du code dans cet amswer: https://instagram.com/p/BY-57nMFUvy/ à ma vue d'ensemble. Le référentiel lié _does_ utilise 'mouseDown (avec:)' sur le contrôleur de vue. –

+0

Comme suggéré dans les commentaires là-bas, j'ai fini par surcharger 'validateProposedFirstResponder: forEvent:' sur la vue générale, pour retourner 'true' pour une certaine sous-classe' NSView'. –

+0

Vous avez raison sur 'mouseDown (avec:)' et le contrôleur. – Willeke