Domanda

Ho un NSCollectionView di lavoro con un minore, ma critico, eccezione. Ottenere ed evidenziando l'elemento selezionato all'interno della raccolta.

Ho avuto tutto questo lavoro prima di Snow Leopard, ma qualcosa sembra essere cambiato e io non riesco a mettere il dito su di esso, così ho preso il mio NSCollectionView destra di nuovo a un test di base e seguito la documentazione di Apple per la creazione di un NSCollectionView qui:

http://developer.apple. com / mac / biblioteca / documentazione / cacao / concettuale / CollectionViews / Introduzione / Introduction.html

La vista di raccolta funziona bene seguendo la guida di avvio rapido. Tuttavia, questa guida non discute selezione diversa "There are such features as incorporating image views, setting objects as selectable or not selectable and changing colors if they are selected".

Usando questo come esempio sono andato alla fase successiva di legare il controller di array al NSCollectionView con il controller selectionIndexes chiave, pensando che questo avrebbe associare qualsiasi scelta che faccio tra il NSCollectionView e il controller di array e sparando quindi fuori un KVO notifica. Ho anche impostato il NSCollectionView per essere selezionabile in IB.

Non sembra esserci nessun delegato di selezione per NSCollectionView e, a differenza maggior parte delle viste cacao dell'interfaccia utente, non sembra esserci alcuna evidenziazione di default selezionato.

Quindi il mio problema tratta veramente basso per un problema analogo, ma di due questioni distinte.

  1. Come faccio a catturare una selezione di un elemento?
  2. Come faccio a visualizzare un punto culminante di un articolo?

guide di programmazione di NSCollectionView sembrano essere pochi e rari e la maggior parte le ricerche tramite Google sembrano tirare su pre-neve implementazioni Leopard, oppure utilizzare la visualizzazione in un file XIB separato.

Per questi ultimi (file XIB separato per la vista), non vedo il motivo per cui questo dovrebbe essere un pre-requisito altrimenti avrei sospettato che Apple non avrebbe incluso la vista nello stesso fascio come elemento vista collezione .

So che questo sta per essere una "non può vedere il legno per gli alberi" problema - quindi sono preparato per il "doh!" momento.

Come al solito, ogni e qualsiasi aiuto molto apprezzato.

Aggiorna 1

OK, così ho pensato di trovare l'elemento selezionato (s), ma non hanno ancora capire l'evidenziazione. Per gli interessati sul calcolare gli elementi selezionati (supponendo che si sta seguendo la guida di Apple):

Nel controllore (nel mio caso di test App Delegato) ho aggiunto il seguente:

In awakeFromNib

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

Nuovo metodo

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

Non dimenticare di dealloc per i non-GC

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

Ancora alla ricerca per la risoluzione clou ...

Aggiorna 2

Ha preso il consiglio di Macatomy ma aveva ancora un problema. Distacco i metodi della classe rilevanti per vedere dove ho sbagliato.

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
È stato utile?

Soluzione

La sua non è troppo difficile da fare. Assicurarsi che "Selezione" è abilitata per la NSCollectionView in Interface Builder. Poi nella sottoclasse NSView che si sta utilizzando per la visualizzazione del prototipo, dichiarare una proprietà chiamata "selezionato":

@property (readwrite) BOOL selected;

codice aggiornato QUI: (aggiunto chiamata super)

sottoclasse NSCollectionViewItem e sovrascrivere -setSelected:

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

Poi si deve aggiungere il codice in drawRect del vostro vista prototipo: metodo per disegnare il momento clou:

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

Questo semplicemente riempie la vista in blu quando la sua scelta, ma che possono essere personalizzati per disegnare l'evidenziazione qualsiasi modo si desidera. Ho usato questo nei miei proprie applicazioni e funziona benissimo.

Altri suggerimenti

Se un colore di sfondo diverso sarà sufficiente come un punto culminante, si può semplicemente utilizzare un NSBox come l'elemento principale per voce della raccolta vista. Riempire il NSBox con il colore di evidenziazione della vostra scelta. Impostare il NSBox su Personalizzata in modo che il riempimento funzionerà. Impostare il NSBox a trasparente.

Associare l'attributo trasparenza del NSBox all'attributo selezionato di file proprietario (insieme di elementi) Impostare il trasformatore valore per il trasparente legame NSNegateBoolean.

Ho cercato di collegare l'interfaccia screenshot builder ma sono stato respinto bcos Sono un principiante: - (

Si può anche andare in un altro modo, se non sei sottoclassi NSView per la visualizzazione prototipo.

Nel vostro sottoclasse NSCollectionViewItem esclusione 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;
}

E naturalmente, come detto da tutte le persone sagge prima di me, assicurarsi che "Selezione" è abilitata per la NSCollectionView in Interface Builder.

Dal momento che nessuna delle risposte esistenti lavorato super bene per me, ecco il mio prendere su di esso. Modificare la sottoclasse della voce CollectionView a SelectableCollectionViewItem. Ecco che è il codice. Viene fornito con una proprietà textColor associabile per collegare la vostra etichetta di testo textColor vincolante.

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

Nel mio caso ho voluto un'immagine (segno di spunta) per indicare la selezione di oggetti. Trascinare un ImageWell al pennino insieme di elementi. Impostare l'immagine desiderata e segnare come nascosto. Vai a attacchi ispettore e legarsi attributo nascosto a Collection Visualizza Articolo.

entrare descrizione dell'immagine qui

(Nel mio caso avevo creato un pennino separato per CollectionViewItem, per cui il suo binded proprietario del file. Se questo non è il caso e la vista: L'articolo è nella stessa pennino come il CollectionView quindi associare alla Collezione Visualizza Articolo)

Imposta percorso della chiave modello come selected e trasformatore Valore da NSNegateBoolean. Quello ora ogniqualvolta le singole cellule / articoli sono selezionati l'immagine sarà visibile, indicando l'selezione.

L'aggiunta alla risposta di Alter.

Per impostare NSBox come elemento principale. È sufficiente creare un nuovo documento IB (dire collectionItem) e trascinare un NSBox per la zona vuota. Ora aggiungere tutti gli elementi, come richiesto all'interno della scatola. Ora cliccate su File del proprietario e impostare classe personalizzata come NSCollectionViewItem.

entrare descrizione dell'immagine qui

E nel pennino in cui viene aggiunto NSCollectionView cambiare il nome pennino per CollectionViewItem

entrare descrizione dell'immagine qui

Nel NSBox, legare i rimanenti elementi a Files Owner. Per un'etichetta, sarebbe simile a:

entrare descrizione dell'immagine qui

Ora per ottenere il colore di evidenziazione come Alter menzionato nella sua risposta, impostare la combinazione di colore desiderata nell'opzione Colore di riempimento, impostare il NSBox a trasparente e rilegare la trasparenza attributo come di seguito:

entrare descrizione dell'immagine qui

Ora, quando si selezionano Collection Visualizzare gli articoli si dovrebbe essere in grado di vedere il colore di riempimento della casella.

Nel vostro NSCollectionViewItem sottoclasse, isSelected override e cambiamento di colore del livello di sfondo. Prova in MacOS 10.14 e 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
    }
  }
}

Questo è stato fantastico, grazie molto! Stavo lottando con questo!

Per chiarire per gli altri:

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

Sostituire PrototypeView * con il nome del prototipo nome della classe.

Nel caso in cui si sta scavando in giro per la soluzione Swift aggiornato, vedere questa risposta .

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

Ecco la completa Swift NSCollectionViewItem con la selezione. Non dimenticare di impostare il NSCollectioView a selezionabili in IB o di programmazione. Testato sotto MacOS Mojave (10.14) e 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
}
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top