Frage

in meinem Kakao Anwendung, ich brauche eine benutzerdefinierte NSCell für eine NSTableView. Diese NSCell Unterklasse enthält eine benutzerdefinierte NSButtonCell für einen Klick (und zwei oder drei NSTextFieldCells für Textinhalte) Handhabung. Sie werden im Folgenden ein vereinfachtes Beispiel für meinen Code finden.

@implementation TheCustomCell

- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
   // various NSTextFieldCells
   NSTextFieldCell *titleCell = [[NSTextFieldCell alloc] init];
   ....
   // my custom NSButtonCell
   MyButtonCell *warningCell = [[MyButtonCell alloc] init];
   [warningCell setTarget:self];
   [warningCell setAction:@selector(testButton:)];
   [warningCell drawWithFrame:buttonRect inView:controlView];
}

Das Problem, das ich bin stecke mit ist: Was ist der beste / richtige Weg, um die Taste zu bekommen (genauer: die NSButtonCell)? In diesem NSCell zur Arbeit richtig „Arbeit“ bedeutet: Trigger die zugeordnete Aktion Nachricht und zeigt das alternative Bild, wenn darauf geklickt. Out of the box, ist die Schaltfläche nicht alles tun, wenn darauf geklickt wird.

Information / Lesungen zu diesem Thema ist schwer zu finden. Die einzigen Beiträge, die ich im Netz gefunden wies mich auf die Umsetzung

- (BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame ofView:(NSView *)controlView untilMouseUp:(BOOL)untilMouseUp; 

Ist dies der richtige Weg, es zu tun ??? Implement trackMouse: in meinem enthält NSCell und dann nach vorne Um das Event in NSButtonCell? Ich würde die NSButtonCell selbst erwartet haben zu wissen, was zu tun ist, wenn es angeklickt wird (und ich sah die trackMouse: Methoden mehr in cunjunction mit wirklich Tracking Mausbewegungen - nicht als Stützrad für ‚Standard‘ Klickverhalten). Aber es scheint, wie es dies nicht tut, wenn sich in einer Zelle eingeschlossen ... Es scheint, ich habe nicht das große Bild auf individuellen Zellen erfaßt, doch, -)

würde ich mich freuen, wenn jemand diese Frage beantworten könnte (oder mich zu einem gewissen Tutorial oder der Punkt wie) aus seiner eigenen Erfahrung -. Und sagen Sie mir, , wenn ich auf dem richtigen Weg bin

Vielen Dank im Voraus, Tobi

War es hilfreich?

Lösung

Die Mindestanforderungen sind:

  • Nach links Maus nach unten auf die Schaltfläche, muss sie gedrückt dargestellt wird, wenn die Maus über sie ist.
  • Wenn die Maus dann Meldungen über die Schaltfläche, Ihre Zelle muss die entsprechende Aktion Nachricht senden.

Um die Taste gedrückt Look zu machen, müssen Sie die Schaltfläche Zelle highlighted Eigenschaft gegebenenfalls aktualisieren. Ändern des Zustands allein wird dies nicht erreichen, aber was Sie wollen, ist für die Taste, wenn ihre Zustände, wenn und nur hervorzuheben ist NSOnState.

die Aktion Nachricht senden, müssen Sie sich bewusst sein, wenn die Maustaste losgelassen wird, und dann -[NSApplication sendAction:to:from:] verwenden, um die Nachricht zu senden.

Um in der Lage zu sein, diese Nachrichten zu senden, müssen Sie in die Ereignisverfolgungsverfahren durch NSCell vorgesehen einzuhaken. Beachten Sie, dass alle diese Tracking-Methoden, mit Ausnahme der letzten, -stopTracking:... Methode, einen Boolean zurückgeben, die Frage zu beantworten: „Haben Sie Tracking-Nachrichten behalten möchten zu erhalten?“

Die letzte Wendung ist, dass, um überhaupt keine Tracking-Nachrichten gesendet zu werden, müssen Sie -hitTestForEvent:inRect:ofView: implementieren und eine entsprechende Bitmaske von NSCellHit... Werte zurückgeben. Insbesondere dann, wenn der Wert zurückgegeben nicht in den NSCellHitTrackableArea Wert haben, werden Sie keine Tracking-Nachrichten erhalten!

Also, auf einem hohen Niveau, Ihre Implementierung wird in etwa so aussehen:

- (NSUInteger)hitTestForEvent:(NSEvent *)event
                       inRect:(NSRect)cellFrame
                       ofView:(NSView *)controlView {
    NSUInteger hitType = [super hitTestForEvent:event inRect:cellFrame ofView:controlView];

    NSPoint location = [event locationInWindow];
    location = [controlView convertPointFromBase:location];
    // get the button cell's |buttonRect|, then
    if (NSMouseInRect(location, buttonRect, [controlView isFlipped])) {
        // We are only sent tracking messages for trackable areas.
        hitType |= NSCellHitTrackableArea;
    }
    return hitType;
}

+ (BOOL)prefersTrackingUntilMouseUp {
   // you want a single, long tracking "session" from mouse down till up
   return YES;
}

- (BOOL)startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView {
   // use NSMouseInRect and [controlView isFlipped] to test whether |startPoint| is on the button
   // if so, highlight the button
   return YES;  // keep tracking
}

- (BOOL)continueTracking:(NSPoint)lastPoint at:(NSPoint)currentPoint inView:(NSView *)controlView {
   // if |currentPoint| is in the button, highlight it
   // otherwise, unhighlight it
   return YES;  // keep on tracking
}

- (void)stopTracking:(NSPoint)lastPoint at:(NSPoint)stopPoint inView:(NSView *)controlView mouseIsUp:(BOOL)flag {
   // if |flag| and mouse in button's rect, then
   [[NSApplication sharedApplication] sendAction:self.action to:self.target from:controlView];
   // and, finally,
   [buttonCell setHighlighted:NO];
}

Andere Tipps

Der Punkt des NSCell Subklassen ist Verantwortung zu trennen für die Darstellung und Handhabung gemeinsamen UI-Elemente (die Kontrollen) von der Sicht- und Ereignis-Hierarchie Verantwortlichkeiten der NSView Klassen. Diese Paarung ermöglicht jedes größere Spezialisierung und Variabilität zu schaffen, ohne das andere zu belasten. Schauen Sie sich die große Anzahl von NSButton Instanzen eines in Cocoa erstellen können. Stellen Sie sich vor, die Anzahl der NSButton Unterklassen, die, wenn diese Spaltung in der Funktionalität existieren würde nicht vorhanden wäre!

Mit Design-Mustersprache, die Rollen zu beschreiben:. Ein NSControl fungiert als Fassade versteckte Details seiner Zusammensetzung von seinen Kunden und vorbei Ereignisse und Rendering-Nachrichten an seine NSCell Instanz, die als Delegierter fungiert

Da Ihre NSCell Unterklasse Unterklasse anderer NSCell Instanzen innerhalb seiner Zusammensetzung enthält, sie nicht mehr direkt auf diese Ereignismeldungen aus der NSControl Instanz empfängt, die in der Ansichtshierarchie ist. Um somit für diese Zell Instanzen Ereignismeldungen aus der Ereignisse Responder-Kette (von der Ansichtshierarchie), Ihre Zelle Instanz muss passieren entlang dieser relevanten Ereignisse zu empfangen. Sie haben die Arbeit der NSView Hierarchie neu zu erstellen.

Dies ist nicht unbedingt eine schlechte Sache. Durch das Verhalten von NSControl replizieren (und seiner NSView geordnete Klasse), aber in einer NSCell Form, können Sie die Ereignisse filtern, weitergegeben an Ihre Unterzellen nach Ort, Ereignistyp oder anderen Kriterien. Der Nachteil ist die Replikation der Arbeit von NSView/NSControl beim Aufbau der Filterung und Management-Mechanismus.

So in Ihrer Schnittstelle entwerfen, müssen Sie prüfen, ob die NSButtonCell (und NSTextFieldCells) sind besser in NSControls in der normalen Ansicht Hierarchie oder als Teilzellen in Ihrer NSCell Unterklasse. Es ist besser, um die Funktionalität zu nutzen, die bereits für Sie in einer Code-Basis als zu existiert neu erfinden sie (und sie weiter später beibehalten) unnötig.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top