Frage

Ich habe eine Arbeits NSCollectionView mit einer kleineren, aber kritisch, Ausnahme. Erste und Markieren des ausgewählten Element in der Sammlung.

Ich habe alle hatten diese Arbeit vor Snow Leopard, aber etwas scheint sich geändert zu haben, und ich kann nicht ganz meine Finger legen auf sie, so dass ich meine NSCollectionView nahm gleich wieder auf ein Basistest und folgte Apples Dokumentation für die Erstellung von ein NSCollectionView hier:

http://developer.apple. com / mac / library / DOKUMENTATION / Cocoa / Conceptual / CollectionViews / Einführung / introduction.html

Die Sammlung Ansicht funktioniert gut im Anschluss an die Schnellstartanleitung. Allerdings ist diese Führung nicht Auswahl anders als "There are such features as incorporating image views, setting objects as selectable or not selectable and changing colors if they are selected" diskutieren.

Mit diesem als Beispiel ich mit dem nächsten Schritt ging den Array-Controller der Bindung an die NSCollectionView mit der Controller Schlüssel selectionIndexes, denkt, dass dies eine beliebige Auswahl binden würde ich zwischen den NSCollectionView machen und den Array-Controller und damit aus einem KVO Brennen Benachrichtigung. Ich habe auch die NSCollectionView in IB wählbar sein.

Es scheint keine Auswahl Delegat für NSCollectionView zu sein, und im Gegensatz zu den meisten Cocoa UI Ansichten, erscheint Highlight nicht standardmäßig aktiviert zu sein.

Also mein Problem kommt auf ein ähnliches Problem wirklich, aber zwei verschiedene Fragen.

  1. Wie erfasse ich eine Auswahl eines Artikels?
  2. Wie kann ich ein Highlight eines Artikels?

NSCollectionView des Programmführern scheinen dünn gesät und die meisten Suchanfragen über Google zu sein scheinen Implementierungen zu ziehen Pre-Snow Leopard oder den Blick in einer separaten XIB-Datei verwenden.

Für letztere (getrennte XIB-Datei für die Ansicht), ich sehe nicht, warum dies eine Voraussetzung sein sollte, sonst hätte ich vermutet habe, dass Apple nicht die Ansicht im gleichen Bündel wie die Sammlungsansicht Artikel enthalten ist, .

Ich weiß, dass dies ein sein wird Problem „kann nicht das Holz für die Bäume sehen“ - „doh“ so bin ich für die vorbereitet Moment.

Wie üblich, jede und alle Hilfe sehr geschätzt.

Update 1

OK, so dachte ich, das ausgewählte Element zu finden (s), aber noch die Markierung Figur. Für die interessiert auf die ausgewählten Elemente Bezifferung (vorausgesetzt, Sie auf das Apple-Führung folgen):

In der Steuerung (in meinem Testfall der App Delegate) Ich habe die folgenden:

In awakeFromNib

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

Neue Methode

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

Vergessen Sie nicht zu dealloc für nicht-GC

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

Still für die Highlight Auflösung der Suche ...

Update 2

Nahm Macatomy Rat aber noch ein Problem hatte. die entsprechenden Klassenmethoden Posting zu sehen, wo ich weg falsch haben.

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
War es hilfreich?

Lösung

Es ist nicht allzu schwer zu tun. Stellen Sie sicher, „Auswahl“ für die NSCollectionView im Interface Builder aktiviert. Dann in der NSView Unterklasse, die Sie für Ihre Prototyp-Ansicht verwenden, deklarieren Sie eine Eigenschaft namens „ausgewählt“:

@property (readwrite) BOOL selected;

AKTUALISIERT CODE HIER: (hinzugefügt Super Call)

Subclass NSCollectionViewItem und Überschreibung -setSelected:

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

Dann müssen Sie Code in Ihrem Prototyp Ansicht des drawRect hinzuzufügen: Methode, um die Markierung ziehen:

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

Das nur einfach die Aussicht in blau füllt, wenn seine ausgewählt, aber das kann angepasst werden der Höhepunkt, wie Sie wollen zu ziehen. Ich habe dies in meinen eigenen Anwendungen verwendet und es funktioniert super.

Andere Tipps

Wenn eine andere Hintergrundfarbe als Highlight ausreicht, könnte man einfach eine NSBox als Root-Element für Dich Auflistelement Ansicht verwenden. Füllen Sie das NSBox mit der Highlight-Farbe Ihrer Wahl. Stellen Sie die NSBox auf Custom so wird die Füllung arbeiten. Stellen Sie den NSBox zu transparent.

Binden Sie die Transparenz-Attribut des NSBox auf das ausgewählte Attribut der Datei-Besitzer (Sammlung Item) Setzen Sie den Wert Transformator für die transparente Bindung an NSNegateBoolean.

Ich habe versucht, Interface Builder Screenshots zu befestigen, aber ich wurde abgelehnt bcos ich ein Neuling bin: - (

Sie können auch einen anderen Weg gehen, wenn Sie nicht NSView für Ihre protoype Ansicht Subklassen.

In Ihrer subclassed NSCollectionViewItem Überschreibung 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;
}

Und natürlich sagte, die von allen den klugen Menschen vor mir, stellen Sie sicher, „Selection“ für die NSCollectionView im Interface Builder aktiviert.

Da keine der vorhandenen Antworten super geklappt gut für mich, hier ist mein nehmen auf sie. Ändern Sie die Unterklasse der Collection Artikel zu SelectableCollectionViewItem. Hier ist es der Code. Kommt mit einer bindungsfähigen Eigenschaft textcolor für Ihre Text Label Textfarbe Bindung an Einhaken.

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

In meinem Fall wollte ich ein Bild (Häkchen) Auswahl des Objekts anzuzeigen. Ziehen Sie eine Imagewell an den Sammelgegenstand Feder. Stellen Sie das gewünschte Bild und markieren Sie ihn als versteckt. Zum Bindungen Inspektor und binden versteckt Attribut-Sammlung Ansicht Artikel.

eingeben Bild Beschreibung hier

(In meinem Fall habe ich eine separate Feder für CollectionViewItem geschaffen hatte, so seine binded auf Datei-Besitzer. Ist dies nicht der Fall ist und Artikelansicht ist in der gleichen Feder wie die Collection dann binden Sammlung View Item)

Set Modell Schlüsselpfad als selected und Wert Transformator NSNegateBoolean. Das ist es jetzt, wenn die einzelnen Zellen / Elemente sind das Bild ausgewählt sichtbar sein wird, damit die Auswahl angezeigt wird.

Das Hinzufügen Alten Antwort.

So legen NSBox als Stammelement. Erstellen Sie einfach ein neues IB-Dokument (sagen CollectionItem) und einen NSBox in dem leeren Bereich ziehen. Nun fügen Sie alle Elemente, wie in der Box erforderlich. Jetzt auf Datei-Besitzer klicken und stellen Sie Kundenspezifische Klasse als NSCollectionViewItem.

eingeben Bild Beschreibung hier

Und in der Spitze, wo NSCollectionView Änderung für CollectionViewItem die Spitze Namen hinzugefügt wird

eingeben Bild Beschreibung hier

In der NSBox, bindet die übrigen Elemente zu Files Owner. Für ein Etikett wäre es ähnlich sein:

eingeben Bild Beschreibung hier

Jetzt die Markierungsfarbe erhalten, wie Alter in seiner Antwort erwähnt, stellen Sie die gewünschte Farbkombination in der Füllfarbe Option, stellen Sie die NSBox zu transparent und binden die Transparenz-Attribut wie folgt:

eingeben Bild Beschreibung hier

Nun, wenn Sammlung Ansicht Artikel ausgewählt werden, sollten Sie in der Lage sein, die Füllfarbe der Box zu sehen.

In Ihrer NSCollectionViewItem Unterklasse überschreiben isSelected und ändern Hintergrundfarbe der Schicht. Test in macOS 10.14 und 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
    }
  }
}

Das war genial, vielen Dank! Ich war mit diesem zu kämpfen!

Um zu klären, für den anderen:

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

Ersetzen PrototypeView * mit dem Namen Ihres Prototyp Klassennamen.

Falls Sie graben um für die Lösung Swift aktualisiert, sehen diese Antwort .

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

Dies ist die komplette Swift NSCollectionViewItem mit Auswahl. Vergessen Sie nicht die NSCollectioView wählbarer in IB oder programmatisch zu setzen. Getestet unter macOS Mojave (10,14) und 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
}
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top