2010-05-20 9 views
30

Tengo una súper vista, que tiene 2 subvistas. Estas subvistas están superpuestas.¿Cómo puedo hacer que un NSView se mueva al frente de todos los NSViews?

Cada vez que elijo una vista desde un menú, la vista correspondiente debe convertirse en la vista frontal y manejar las acciones. es decir, debería ser la subvista más frontal.

acceptsFirstResponder todo funciona bien. Pero los eventos del mouse hacia abajo se envían a la subvista superior que se configuró.

Saludos, Dhana

+0

Tenga en cuenta que: "Nota: Por motivos de rendimiento, cacao no hace cumplir el recorte entre los puntos de vista de hermanos ..." Y además! "Cocoa no ... garantiza la correcta invalidación y el comportamiento de dibujo cuando se superponen las vistas de hermanos." Como dice en el manual:" Si desea que una vista se dibuje frente a otra vista, debe hacer que la vista frontal sea una subvista (o un descendiente) de la vista posterior. " (de la Programación de vistas) Guía en el doco de OSX) – Fattie

Respuesta

35

Ésta es otra manera de lograr esto que es un poco más claro y conciso:

[viewToBeMadeForemost removeFromSuperview]; 
[self addSubview:viewToBeMadeForemost positioned:NSWindowAbove relativeTo:nil]; 

por la documentación para este método, cuando usa relativeTo:nil, la vista se agrega arriba (o debajo, con NSWindowBelow) a todos sus hermanos.

+3

Existe un problema con el enfoque anterior. Primero, cuando envía ** removeFromSuperview ** a una vista, se libera. Por lo tanto, primero debe conservar la vista, y luego equilibrar el retener original con un En segundo lugar, tiene la ventaja de eliminar y agregar la vista a la jerarquía (lo que puede ser costoso según la complejidad de su jerarquía de vistas). hy). Hay otra forma de hacerlo que evita tener que eliminar y agregar vistas desde la jerarquía de vista utilizando la función de clasificación de subvista incorporada de NSView. Vea abajo. – Dalmazio

+0

Creo que las dos líneas de código siguen en el mismo bucle de evento, por lo que viewToBeMadeForemost no se lanzará antes de la segunda línea. –

+0

@LiFumin, eso es incorrecto. Estás asumiendo que removeFromSuperview libera automáticamente la vista, o que el otro código se lanzó automáticamente. Del documento de -removeFromSuperview: "La vista también se libera: si planea reutilizarla, asegúrese de retenerla antes de enviar este mensaje y liberarla como corresponda al agregarla como una subvista de otro NSView". Dalmazio tiene razón, la vista debe conservarse. Esta solución también tiene problemas con respecto a la ruptura de restricciones, etc., me imagino. No debería ser la respuesta aceptada. – bhaller

1

A continuación código dado debería funcionar bien ..

NSMutableArray *subvies = [NSMutableArray arrayWithArray:[self subviews]];//Get all subviews.. 

    [viewToBeMadeForemost retain]; //Retain the view to be made top view.. 

    [subvies removeObject:viewToBeMadeForemost];//remove it from array 

    [subvies addObject:viewToBeMadeForemost];//add as last item 

    [self setSubviews:subvies];//set the new array.. 
+0

A menos que use ARC ... – geowar

+0

Esta debería ser la respuesta aceptada, ya que está más cerca de ser correcta que las demás. Sin embargo, tenga en cuenta que debe hacer una versión [viewToBeMadeForemost]; hay una fuga – bhaller

11

Otra forma es utilizar NSView sortSubviewsUsingFunction: context: método para reordenar una colección de vistas de hermanos a su gusto. Por ejemplo, definir su función de comparación:

static NSComparisonResult myCustomViewAboveSiblingViewsComparator(NSView * view1, NSView * view2, void * context) 
{  
    if ([view1 isKindOfClass:[MyCustomView class]])  
     return NSOrderedDescending;  
    else if ([view2 isKindOfClass:[MyCustomView class]])  
     return NSOrderedAscending;  

    return NSOrderedSame; 
} 

Entonces, cuando usted quiere asegurarse de que su vista personalizada mantiene por encima de todos los puntos de vista de hermanos, envía este mensaje a supervista de la vista personalizada:

[[myCustomView superview] sortSubviewsUsingFunction:myCustomViewAboveSiblingViewsComparator context:NULL]; 

Como alternativa, puede mueva este código a la supervista y envíe el mensaje sortSubviewsUsingFunction: context: a self en su lugar.

+2

@Jonathan. Eso es para UIViews que son parte del marco de iOS. La pregunta es sobre NSViews que se usan para aplicaciones OS X. – Mathias

+0

Esto funciona, pero parece hacer que el orden del resto de las subvistas sea aleatorio, ya que el documento dice "NSOrderedSame si su orden no es importante". Una solución que preserve el orden del resto de las vistas sería mucho mejor. Además, el uso de IsKindOfClass: aquí es raro; la pregunta no indica que se están utilizando subclases de vista personalizada, o que las subvistas de hermanos a reordenar son clases diferentes. – bhaller

-10

Usted puede intentar esto:

[viewToBeMadeFirst.window makeKeyAndOrderFront:nil]; 
+0

sí, este funciona para mí: [self.window makeKeyAndOrderFront: self]; –

+8

Estamos hablando de NSView, no NSWindow – NSAddict

4

pude conseguir que esto funcione sin llamar removeFromSuperView

// pop to top 
[self addSubview:viewToBeMadeForemost positioned:NSWindowAbove relativeTo:nil]; 
+0

¿Esto crea una nueva vista en lugar de usar la vista existente? – Krishnabhadra

+1

Esto causó que la aplicación se cuelgue para siempre. –

+0

Si esto funciona, es solo por accidente; los documentos no dan garantías en cuanto al comportamiento de agregar una vista que ya está agregada. – bhaller

1

Esto se puede conseguir con sólo añadir la vista de nuevo; no creará otra instancia de esto.

[self addSubview:viewToBeMadeForemost]; 

Puede registrar el número de subvistas antes y después de que se ejecute esta línea de código.

+1

Si esto funciona, es solo por accidente; los documentos no dan garantías en cuanto al comportamiento de agregar una vista que ya está agregada. – bhaller

0

Para mover una vista hacia el frente, debe colocarse como el último elemento en la matriz de subvistas. He aquí una solución Swift 3.0:

func bringChildToFrontWith(viewIdentifier: Int) { 
    var subViewArray = self.subviews // Apple docs recommend copying subViews array before operating on it, as it "can be changed at any time" 
    for ix in 0 ..< subViewArray.count { 
     if let childView = subViewArray[ix] as? MyViewSubClass { 
      if childView.myViewSubClassIdentifier == viewIdentifier { 
       let topItem = subViewArray[ix]; 
       subViewArray.remove(at: ix) 
       subViewArray.append(topItem) 
       self.contentView.subviews = subViewArray 
      } 
     } 
    } 
} 
Cuestiones relacionadas