NSMatrix + NSButton (Check Box) + state

  • NSMatrix + NSButton (Check Box) + state

    Hallo,

    ich habe eine Matrix, die NSButtonCell Check Boxes enthält und über ihre bindings (content, contentValues) befüllt wird. Das klappt wunderbar. Allerdings sehe ich keine Möglichkeit den Status (checked, unchecked) der Cells zu definieren ähnlich wie in einer Spalte einer Tabelle. Markiere ich eine einzelne Zelle in der Matrix kann ich dies natürlich einstellen.

    Oder habe ich nur wieder was überlesen?
    Die Objective-Cloud ist fertig wenn sie fertig ist. Beta heißt Beta.

    Objective-C und Cocoa Band 2: Fortgeschrittene
    Cocoa/Objective-C Seminare von [co coa:ding].
  • Es ist ja wirklich etwas spät und ich habe ausch schon etwas getrunken ...

    Aber ich verstehe das nicht ganz:
    Eine Matrix ist dazu da, verschiedene gleichartige Elemente zusammenzufassen. Klassisch und klar ist das bei Radio-Buttons, da nur eines selektiert sein kann. Aber wie will man Check-Boxes-zusammenfassen? Jedes sein eigenes State? Wo liegt die Klammerung des Matrix-Views? Wieso kommst du überhaupt auf dessen Verwendung?

    Kannst du es an einem konkretreten Beispiel mir verständlicher machen?
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Ja kann ich.

    Vorhanden: Entity "Column" deren Inhalt die Spalten eines TableViews beschreibt (titel, identifier, position, breite, sichtbar oder nicht). Dazu möchte ich nun ein entsprechendes Interface für den Benutzer anbieten, in dem er die verfügbaren Spalten sieht und über eine Checkbox jede Spalte für sich visible oder hidden definieren kann - ähnlich wie in iTunes. Momentan realisiere ich die UI mit einer NSTableView, deren Spalte 0 checkboxes enthält und Spalte 1 die Beschreibung der jeweiligen Column.

    Anbei ein Screenshot von iTunes. So will ich das auch machen.
    Die Objective-Cloud ist fertig wenn sie fertig ist. Beta heißt Beta.

    Objective-C und Cocoa Band 2: Fortgeschrittene
    Cocoa/Objective-C Seminare von [co coa:ding].
  • Ja, das Binding wäre allerdings eher selectedObjects oder ähnlich. Der aktive Button ist ja der in der Matrix selektierte. Das übertragen, müsste man eben mehrere selekktieren können. Ein solches Binding existiert iindessen nicht. :(
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Gut, das GUI verstehe ich jetzt. Aber wieso bindest du nicht jede Checkbox einzeln? Oder anders herum: Was willst du mit einer Matrix erreichen?

    Ah, hast du die einzelnen Spalten in einem Array stehen?
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Ich unterstelle mal die Antwort auuf meine letzte Frage mit einem "Ja, aber klar doch!"

    Dann fielen mir folgende Möglichkeiten ein:

    a) Ableitung von NSMatrix mit einem neuen Bindin selectedObjects oder selectedIndexes oder so etwas. In der Observierung setzt bzw. löschst du da Häkchen. Ah, mutmaßlich kannst du einfach die Bindung an deine Einträge weiterreichen.

    Quellcode

    1. - (void)observeValueForKey:… {
    2. // Alle observierungen abmelden
    3. NSEnumerator* itemsEnum = [oldArray objectEnumerator];
    4. id item;
    5. while( (object = [...]) ) {
    6. [item unbind:@"stateOderWasAuchImmer"];
    7. }
    8. // Den super-Kram machen, also rows und so
    9. // Und jetzt die State-Eigenschaft der neuen Buttons jeweils binden, Schleife wie oben.
    10. }
    Alles anzeigen


    b) Selbst aufbauen. (Ok, den Gedanken hattest du auch schon.)

    c) Ich finde grundsätzlich ein Table-View (ohne Header) eleganter und würde das so machen. Anstelle von Häkchen einfach Selection nehmen: Was selektiert ist, wird angezeigt.

    d) Bei einem Table-View bei jeder Selektierung einfach eine Check-Box toggeln.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Eben, du erzeugst die ja konkret im Code, um sie dann in eine abstrakte Collection zu stecken, um dann wieder konkret darauf zuzugreifen. In gewisser Weise schießt du dir selbst ins Knie.

    Aber dennoch, ich weiß ja nicht, welchen praktischen Anspruch du daran hast: Interessant fände ich eine Ableitung schon. Außerdem wäre es eine nette Fingerübung für eigene Bindings. Aber ich interessiere mich ja ohnehin mehr für das Wie als für das, was am Ende dabei herumkommt ...
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Also bindings zu exposen und damit umzugehen kann ich schon lieber Tom :)

    Ich werde wohl die Lösung mit der NSTableView + deren selection abfangen und dann die Checkbox togglen nehmen. Ist einfach am schnellsten gemacht. Bevor das Programm dann online geht werde ich aber wohl den von dir beschriebenen NSMatrix Subclass realisieren und hier dann anderen zur Verfügung stellen...

    Danke Tom9811 - es war mir ein Vergnügen und wieder sehr aufschlussreich.

    :)
    Die Objective-Cloud ist fertig wenn sie fertig ist. Beta heißt Beta.

    Objective-C und Cocoa Band 2: Fortgeschrittene
    Cocoa/Objective-C Seminare von [co coa:ding].
  • Das dachte ich mir, weshalb ich auch von "Fingerübung" und nicht "Erlernen" sprach, lieber Objcler. :)

    Die hier beschriebene Implementierung ist freilich rudimentär. Ausführlicher habe ich das, wenn mich nicht alles täuscht, in dem KVO-Artikel. Eine 1:n-Observierung ist ja nicht ganz einfach. Insbesondere bberücksichtigt die hier dargestellte Routine nicht das gezielte Hinzufügen und Löschen einzelner Elemente.

    Äääääh, Moment! Das ist ja alles gar nicht notwendig, da die Anzahl ja konstant ist. Geht ja alles viel einfacher: Du überschreiibst in der Ableitung einfach -bind:toObject:bla:bla:bla und vergleichst auf das Binding @"content". Treffer -> Alle Buttons binden. Probleme könnte es nur geben, wenn dann dein Array noch nicht steht oder die Buttons noch nicht gesetzt sind. Aber ich mutmaße mal, dass nach einem Aufruf von [super bind:...] alles seine Richtigkeit hat.

    Ist zwar etwass dirty, dafür nur ein halbes Dutzend Zeilen. Später kann man das -observeValueForKeyPath:… ja immer noch sauber implementieren.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Eine relativ einfache Lösung hab ich gefunden...

    die Matrix einfach vie folgt binden:

    content: arrayController.arrangedObjects
    contentValues: arrayController.arrangedObjects.key
    selectedObjects: einBeliebigerController.checkedContentObjects


    Bei vielen vielen arrangedObjects dürfte das nicht performant genug sein. Aber für meine paar objekte ist dies ausreichend und sehr sehr zielführend.


    Quellcode

    1. - (NSArray *)checkedContentObjects {
    2. NSManagedObjectContext *context = [[NSApp delegate] managedObjectContext];
    3. NSEntityDescription *entity = [NSEntityDescription entityForName:@"YourEntity" inManagedObjectContext:context];
    4. NSPredicate *predicate = [NSPredicate predicateWithFormat:@"checked == 1"];
    5. NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
    6. [request setPredicate:predicate];
    7. [request setEntity:entity];
    8. return [context executeFetchRequest:request error:NULL];
    9. }
    10. - (void)setCheckedContentObjects:(NSArray *)checkedObjects {
    11. [[arrayController arrangedObjects] makeObjectsPerformSelector:@selector(setChecked:) withObject:[NSNumber numberWithBool:NO]];
    12. [checkedObjects makeObjectsPerformSelector:@selector(setChecked:) withObject:[NSNumber numberWithBool:YES]];
    13. }
    Alles anzeigen
    Die Objective-Cloud ist fertig wenn sie fertig ist. Beta heißt Beta.

    Objective-C und Cocoa Band 2: Fortgeschrittene
    Cocoa/Objective-C Seminare von [co coa:ding].