Pregunta

Tengo un trabajo NSCollectionView con una menor de edad, pero crítica, la excepción.Llegar y poner de relieve el elemento seleccionado dentro de la colección.

He tenido todo este trabajo previo a Snow Leopard, pero algo parece haber cambiado y yo no puedo poner mi dedo en él, así que me tomé mi NSCollectionView a la derecha de nuevo a una prueba básica y seguido la documentación de Apple para la creación de un NSCollectionView aquí:

http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Conceptual/CollectionViews/Introduction/Introduction.html

La vista de colección funciona bien siguiendo la guía de inicio rápido.Sin embargo, esta guía no trata sobre la selección de otros que "There are such features as incorporating image views, setting objects as selectable or not selectable and changing colors if they are selected".

Usando esto como un ejemplo, me fui para el siguiente paso de la unión de la Matriz de control a la NSCollectionView con el controlador de tecla selectionIndexes, pensando que esto iba a obligar a cualquier selección que hacer entre el NSCollectionView y el controlador de matriz y por lo tanto de disparar un KVO notificación.También he puesto el NSCollectionView se pueden seleccionar en el IB.

Parece ser que no hay selección delegado para NSCollectionView y a diferencia de la mayoría de Cacao interfaz de usuario de opiniones, parece ser que no hay valor predeterminado seleccionado resaltar.

Así que mi problema realmente se reduce a un problema relacionado, pero con dos preguntas.

  1. ¿Cómo puedo capturar una selección de un elemento?
  2. ¿Cómo puedo ver un punto culminante de un elemento?

NSCollectionView's guías de programación parecen ser pocos y distantes entre sí y la mayoría de las búsquedas a través de Google parecen tirar de pre-Snow Leopard implementaciones, o utilizar la vista por separado en un archivo XIB.

Para el último (por separado archivo XIB para la vista), no veo por qué esto debe ser un pre-requisito de lo contrario me hubiera sospechado que Apple no habría incluido a la vista en el mismo paquete como la vista de colección elemento.

Sé que esto va a ser un "no se puede ver la madera de los árboles" problema - así que estoy preparado para el "doh!" momento.

Como de costumbre, cualquier ayuda muy apreciada.

Actualización 1

OK, así que me imaginé encontrar el elemento seleccionado(s), pero aún no figura el resaltado.Para los interesados en descubrir los elementos seleccionados (suponiendo que usted está siguiendo la guía de Apple):

En el controlador (en mi caso de prueba de la Aplicación Delegado) he añadido el siguiente:

En awakeFromNib

[personArrayController addObserver:self
       forKeyPath:@"selectionIndexes" 
       options:NSKeyValueObservingOptionNew
       context:nil];

Nuevo Método

-(void)observeValueForKeyPath:(NSString *)keyPath 
                     ofObject:(id)object
                       change:(NSDictionary *)change
                      context:(void *)context
{
    if([keyPath isEqualTo:@"selectionIndexes"])
    {
        if([[personArrayController selectedObjects] count] > 0)
        {
            if ([[personArrayController selectedObjects] count] == 1)
            {
                personModel * pm = (PersonModel *) 
                       [[personArrayController selectedObjects] objectAtIndex:0];
                NSLog(@"Only 1 selected: %@", [pm name]);
            }
            else
            {
                // More than one selected - iterate if need be
            }
        }
    }

No olvides dealloc para los no-GC

-(void)dealloc
{
    [personArrayController removeObserver:self 
                               forKeyPath:@"selectionIndexes"];
    [super dealloc];
}

Todavía buscando el punto culminante de la resolución...

Actualización 2

Tomó Macatomy del consejo, pero todavía había un problema.La publicación de los correspondientes métodos de la clase para ver a dónde me ha ido mal.

Mivista.h

#import <Cocoa/Cocoa.h>

@interface MyView : NSView {
    BOOL selected;
}

@property (readwrite) BOOL selected;

@end

Mivista.m

#import "MyView.h"

@implementation MyView

@synthesize selected;

-(id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here.
    }
    return self;
}

-(void)drawRect:(NSRect)dirtyRect
{
    NSRect outerFrame = NSMakeRect(0, 0, 143, 104);
    NSRect selectedFrame = NSInsetRect(outerFrame, 2, 2);

    if (selected)
        [[NSColor yellowColor] set];
    else
        [[NSColor redColor] set];

    [NSBezierPath strokeRect:selectedFrame];
}

@end

MyCollectionViewItem.h

#import <Cocoa/Cocoa.h>
@class MyView;

@interface MyCollectionViewItem : NSCollectionViewItem {

}

@end

"MyCollectionViewItem.m*

#import "MyCollectionViewItem.h"
#import "MyView.h"

@implementation MyCollectionViewItem

-(void)setSelected:(BOOL)flag
{

    [(MyView *)[self view] setSelected:flag];
    [(MyView *)[self view] setNeedsDisplay:YES];
}

@end
¿Fue útil?

Solución

No es demasiado difícil de hacer.Asegúrate de que la "Selección" está habilitado para el NSCollectionView en el Interface Builder.A continuación, en la NSView subclase de que usted está utilizando para el prototipo de vista, declarar una propiedad llamada "seleccionado" :

@property (readwrite) BOOL selected;

ACTUALIZADO EL CÓDIGO AQUÍ:(añadido súper llamada)

Subclase NSCollectionViewItem y reemplazar -setSelected:

- (void)setSelected:(BOOL)flag
{
    [super setSelected:flag];
    [(PrototypeView*)[self view] setSelected:flag];
    [(PrototypeView*)[self view] setNeedsDisplay:YES];
}

Entonces usted necesita para agregar código en su prototipo de vista del drawRect:método para dibujar el punto culminante:

- (void)drawRect:(NSRect)dirtyRect 
{
    if (selected) {
       [[NSColor blueColor] set];
       NSRectFill([self bounds]);
    }
}

Que simplemente llena la vista en azul cuando su seleccionado, pero que puede ser personalizado para dibujar el punto culminante de cualquier manera que usted desea.La he usado en mis propias aplicaciones y funciona muy bien.

Otros consejos

Si un color de fondo diferente bastará como un punto culminante, usted podría simplemente utilizar un NSBox como el elemento raíz para que la colección de punto de vista.Llenar el NSBox con el color de su elección.Establecer el NSBox Personalizado para el relleno de trabajo.Establecer el NSBox transparente.

Obligar a la transparencia atributo de la NSBox para el atributo seleccionado de Propietario del Archivo(Elemento de Colección) Establezca el valor transformador de la transparencia de la unión a NSNegateBoolean.

Traté de colocar Interface builder, capturas de pantalla, pero me fue rechazada bcos soy un novato :-(

También se puede ir de otra manera, si no estás de subclases NSView para su protoype vista.

En su subclases NSCollectionViewItem reemplazar setSelected:

- (void)setSelected:(BOOL)selected
{
    [super setSelected:selected];
    if (selected)
        self.view.layer.backgroundColor = [NSColor redColor].CGColor;
    else
        self.view.layer.backgroundColor = [NSColor clearColor].CGColor;
}

Y por supuesto, como se dijo por todos los sabios de la gente delante de mí, asegúrate de que la "Selección" está habilitado para el NSCollectionView en el Interface Builder.

Dado que ninguna de las respuestas existentes trabajado super bien para mí, aquí está mi opinión sobre ella.Cambio de la subclase de los CollectionView elemento a SelectableCollectionViewItem.Aquí está el código.Viene con un enlazable textColor propiedad para enganchar a su etiqueta de texto textColor enlazando.

@implementation SelectableCollectionViewItem

+ (NSSet *)keyPathsForValuesAffectingTextColor
{
    return [NSSet setWithObjects:@"selected", nil];
}

- (void)viewDidLoad {
    [super viewDidLoad];

    self.view.wantsLayer = YES;
}

- (void) viewDidAppear
{
    // seems the inital selection state is not done by Apple in a KVO compliant manner, update background color manually
    [self updateBackgroundColorForSelectionState:self.isSelected];
}

- (void)updateBackgroundColorForSelectionState:(BOOL)flag
{
    if (flag)
    {
        self.view.layer.backgroundColor = [[NSColor alternateSelectedControlColor] CGColor];
    }
    else
    {
        self.view.layer.backgroundColor = [[NSColor clearColor] CGColor];
    }
}

- (void)setSelected:(BOOL)flag
{
    [super setSelected:flag];
    [self updateBackgroundColorForSelectionState:flag];
}

- (NSColor*) textColor
{
    return self.selected ? [NSColor whiteColor] : [NSColor textColor];
}

En mi caso, quería una imagen(marca de verificación) para indicar la selección del objeto.Arrastre un ImageWell para el Elemento de Recopilación de punta.Establecer la imagen deseada y se marca como oculto.Ir a los enlaces inspector y se unen atributo de oculto a la Vista de Colección Elemento.

enter image description here

(En mi caso, yo había creado un punta para CollectionViewItem, por lo que su enlazadas al dueño del Archivo.Si este no es el caso y Punto de vista es en la misma punta como la CollectionView luego se unen a la Colección de Elemento de Vista)

Modelo de conjunto de la ruta de la clave como selected y el Valor transformador para NSNegateBoolean.No es que ahora cada vez que las células individuales/elementos son seleccionados de la imagen será visible, por lo tanto indica la selección.

La adición de Alterar la respuesta.

Para establecer NSBox como elemento de raíz.Basta con crear una nueva IB documento(decir CollectionItem) y arrastre un NSBox a la zona vacía.Ahora agregar todos los elementos necesarios dentro de la caja.Ahora haga clic en Propietario del Archivo y el conjunto de clases Personalizadas como NSCollectionViewItem.

enter image description here

Y en la punta donde NSCollectionView se añade el cambio de la punta de nombre para CollectionViewItem

enter image description here

En el NSBox, se unen el resto de los elementos a Files Owner.Para una etiqueta sería similar a :

enter image description here

Ahora para obtener el color de resaltado como Alter mencionó en su respuesta, establecer la combinación de colores en el Color de Relleno de la opción, establezca la NSBox transparente y obligar a la transparencia atributo de la siguiente manera:

enter image description here

Ahora, cuando la Colección de la Vista de los Elementos son seleccionados debe ser capaz de ver el color de relleno de la caja.

En su NSCollectionViewItem subclase, anular isSelected y cambiar el color de fondo de la capa.Prueba en macOS 10.14 y Swift 4.2

class Cell: NSCollectionViewItem {

  override func loadView() {    
    self.view = NSView()
    self.view.wantsLayer = true
  }

  override var isSelected: Bool {
    didSet {
      self.view.layer?.backgroundColor = isSelected ? NSColor.gray.cgColor : NSColor.clear.cgColor
    }
  }
}

Este fue impresionante, gracias mucho!yo estaba luchando con esto!

Para clarificar a los demás:

 [(PrototypeView*)[self view] setSelected:flag];
 [(PrototypeView*)[self view] setNeedsDisplay:YES];

Reemplazar PrototypeView* con el nombre de su prototipo nombre de la clase.

En caso de que usted está buscando la actualización de la solución rápida, ver esta respuesta.

class MyViewItem: NSCollectionViewItem {
  override var isSelected: Bool {
      didSet {
        self.view.layer?.backgroundColor = (isSelected ? NSColor.blue.cgColor : NSColor.clear.cgColor)
      }
  }
  etc...
}

Aquí está la completa Swift NSCollectionViewItem con la selección.No olvides poner el NSCollectioView a seleccionables en IB o mediante programación.Probado bajo macOS Mojave (10.14) y la Alta Sierra (10.13.6).

import Cocoa

class CollectionViewItem: NSCollectionViewItem {

private var selectionColor : CGColor {
    let selectionColor : NSColor = (isSelected ? .alternateSelectedControlColor : .clear)
    return selectionColor.cgColor
}

override var isSelected: Bool {
    didSet {
        super.isSelected = isSelected
        updateSelection()
        // Do other stuff if needed
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    view.wantsLayer = true
    updateSelection()
}

override func prepareForReuse() {
    super.prepareForReuse()
    updateSelection()
}

private func updateSelection() {
    view.layer?.backgroundColor = self.selectionColor
}
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top