Question

J'ai NSCollectionView travailler avec un mineur, mais critique, exception. Obtenir et mettre en évidence l'élément sélectionné dans la collection.

J'ai eu tout ce travail avant Snow Leopard, mais quelque chose semble avoir changé et je ne peux pas placer tout mon doigt là-dessus, donc je pris mon NSCollectionView retour à un test de base et suivi de la documentation d'Apple pour la création un NSCollectionView ici:

http://developer.apple. com / mac / bibliothèque / DOCUMENTATION / cacao / conceptuel / CollectionViews / introduction / introduction.html

La vue collection fonctionne très bien en suivant le guide de démarrage rapide. Cependant, ce guide ne traite pas de sélection autre que "There are such features as incorporating image views, setting objects as selectable or not selectable and changing colors if they are selected".

En utilisant cet exemple, je suis allé à l'étape suivante de la liaison du contrôleur Array au NSCollectionView avec le contrôleur selectionIndexes clé, pensant que cela lierait toute sélection que je fais entre le NSCollectionView et le contrôleur RAID et donc tirer au large d'un KVO notification. Je mets aussi le NSCollectionView être sélectionnable dans IB.

Il semble y avoir aucun délégué de sélection pour NSCollectionView et contrairement à la plupart des vues UI Cocoa, il ne semble pas sélectionné par défaut fort.

Alors, mon problème vient vraiment à une question connexe, mais deux questions distinctes.

  1. Comment capturer une sélection d'un article?
  2. Comment afficher un moment fort d'un article?

Les guides de programmation de NSCollectionView semblent être peu nombreux et la plupart des recherches via Google semblent tirer vers le haut des implémentations de Leopard pré-neige, ou utiliser la vue dans un fichier séparé XIB.

Pour ce dernier (fichier XIB séparé pour la vue), je ne vois pas pourquoi cela devrait être une condition préalable, sinon je l'aurais soupçonné qu'Apple aurait pas inclus la vue dans le même faisceau que la vue collection article .

Je sais que cela va être un « ne peut pas voir le bois pour les arbres » question - donc je suis prêt pour le « doh! » moment.

Comme d'habitude, toute aide a beaucoup apprécié.

Mise à jour 1

OK, donc je me suis dit trouver l'élément sélectionné (s), mais doivent encore comprendre la mise en évidence. Pour les intéressés à déterminer les éléments sélectionnés (en supposant que vous suivez le guide Apple):

Dans le contrôleur (dans mon cas de test, le délégué App) J'ajouté ce qui suit:

Dans awakeFromNib

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

Nouvelle méthode

-(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
            }
        }
    }

Ne pas oublier de dealloc pour les non-GC

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

Toujours à la recherche de la résolution de mise en surbrillance ...

Mise à jour 2

a suivi les conseils de Macatomy mais avait encore un problème. Affichage des méthodes de classe pertinentes pour voir où je suis allé mal.

MyView.h

#import <Cocoa/Cocoa.h>

@interface MyView : NSView {
    BOOL selected;
}

@property (readwrite) BOOL selected;

@end

MyView.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
Était-ce utile?

La solution

ne est pas trop difficile à faire. Assurez-vous que « Sélection » est activée pour l'NSCollectionView dans Interface Builder. Ensuite, dans la sous-classe NSView que vous utilisez pour votre vue prototype, déclarer une propriété appelée « sélectionné »:

@property (readwrite) BOOL selected;

ICI CODE MISE À JOUR: (super appel ajouté)

Sous-classe NSCollectionViewItem et remplacer -setSelected:

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

Ensuite, vous devez ajouter du code dans drawRect de votre point de vue prototype: méthode pour dessiner le point culminant:

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

Ce que remplit simplement la vue en bleu lorsque son sélectionné, mais qui peut être personnalisé pour tirer le meilleur moment comme vous le souhaitez. Je l'ai utilisé dans mes propres applications et il fonctionne très bien.

Autres conseils

Si une couleur de fond différente suffira comme un moment fort, vous pouvez simplement utiliser un NSBox comme l'élément racine pour vous vue élément de collection. Remplissez le NSBox avec la couleur de surbrillance de votre choix. Réglez le NSBox sur Personnalisé de sorte que le remplissage fonctionnera. Réglez le NSBox à la transparence.

Liez l'attribut de transparence du NSBox à l'attribut sélectionné du fichier propriétaire (Collection article) Régler le transformateur de valeur pour la liaison transparente à NSNegateBoolean.

J'ai essayé de joindre des captures d'écran de l'interface constructeur, mais je rejetais bcos Je suis un débutant: - (

Vous pouvez aussi aller une autre façon, si vous n'êtes pas NSView pour votre sous-classement vue protoype.

Dans votre setSelected: override NSCollectionViewItem sous-classé

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

Et bien sûr, comme l'a dit tout le peuple sage devant moi, assurez-vous « Sélection » est activée pour le NSCollectionView dans Interface Builder.

Étant donné qu'aucune des réponses existantes a travaillé super bien pour moi, voici mon avis sur la question. Modifier la sous-classe de l'élément CollectionView à SelectableCollectionViewItem. Voici son code. Livré avec une propriété liable textColor pour accrocher l'étiquette de votre texte textColor se liant à.

@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];
}

Dans mon cas, je voulais une image (coche) pour indiquer la sélection d'objet. Faites glisser un ImageWell à la pointe Collection article. Réglez l'image désirée et la marquer comme caché. Aller à l'inspecteur de liaisons et de lier attribut caché à la collection Voir article.

entrer image description ici

(Dans mon cas, j'avais créé une plume séparée pour CollectionViewItem, de sorte que son binded au propriétaire du fichier. Si ce n'est pas le cas et la vue de l'article est de la même plume que la CollectionView se lient alors à la collection Voir article)

Définir chemin de clé modèle comme selected et transformateur Valeur à NSNegateBoolean. Cest maintenant chaque fois que les cellules individuelles / éléments sont sélectionnés l'image sera visible, ce qui indique donc la sélection.

Ajout à la réponse de Alter.

Pour définir NSBox comme élément racine. Il suffit de créer un nouveau document IB (dire collectionItem) et faites glisser une NSBox dans la zone vide. Maintenant, ajoutez tous les éléments comme requis dans la boîte. Cliquez maintenant sur le propriétaire et réglez Custom Class de fichier comme NSCollectionViewItem.

entrer image description ici

Et dans la pointe où NSCollectionView est ajouté changer le nom de plume CollectionViewItem

entrer image description ici

Dans le NSBox, lier les éléments restants à Files Owner. Pour une étiquette, il serait similaire à:

entrer image description ici

Maintenant, pour obtenir la couleur de surlignage comme Alter mentionné dans sa réponse, désirée combinaison de couleurs défini dans l'option Couleur de remplissage, définissez le NSBox à la transparence et lier la transparence attribut comme ci-dessous:

entrer image description ici

Maintenant, quand Collection Afficher les éléments sont sélectionnés, devriez être en mesure de voir la couleur de remplissage de la boîte.

Dans votre sous-classe NSCollectionViewItem, override isSelected et changer la couleur d'arrière-plan de la couche. Test dans macOS 10,14 et 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
    }
  }
}

C'était génial, merci beaucoup! Je luttais avec ceci!

Afin de clarifier pour les autres:

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

Remplacer PrototypeView * avec le nom de votre nom de classe prototype.

Si vous creusez autour de la solution Swift mise à jour, voir cette réponse .

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

Voici le Swift NSCollectionViewItem avec la sélection. Ne pas oublier de mettre la NSCollectioView à sélectionnable dans IB ou par programme. Testé sous Mac OS Mojave (10,14) et High 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
}
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top