Cocoa: NSBox mit Hintergrundfarbe und 3D-Rahmen

Im Beispielcode habe ich eine Subklasse von NSBox erstellt, es funktioniert aber genauso mit jeder anderen Unterklasse von NSView, oder NSView selbst.

Sowohl NSView, als auch seine Unterklasse NSBox bieten leider im Interface-Builder keine Möglichkeit, eine Hintergrundfarbe festzulegen, oder einen rechteckigen 3D-Rahmen zu erzeugen.

[more]

Um diese Effekte zu erreichen, muss man eine Unterklasse von NSView (oder NSBox) erstellen und die Methode

- (void) drawRect: (NSRect)rect
{
}

überschreiben, die dazu dient, das NSView zu »zeichnen«.

Für unser NSView benötigen wir zwei NSRect — eines für den Rahmen und darin ein etwas kleineres, mit dessen Hilfe wir den Hintergrund zeichnen können.

 – (void) drawRect: (NSRect)rect
{ NSRect backgroundRect, borderRect;

//Unser Rahmen-NSRect soll die Maße des Views bekommen borderRect = [self bounds]; //das NSRect für den Hintergrund soll 2 Pixel kleiner sein backgroundRect = NSInsetRect(borderRect, 2.0, 2.0); }
Da wir zwar einen einfarbigen Rahmen um ein NSRectzeichnen können, jedoch leider keinen mehrfarbigen, müssen wir diesen aus mehreren Linien selbst »bauen«. Hierfür benötigen wir die vier Eckpunkte, die wir mittels der NSMin- und NSMax-Funktionen ermitteln können. Die Funktionen erwarten jeweils einen Parameter vom Typ NSRect.
 – (void) drawRect: (NSRect)rect
{
    …
    int minX = NSMinX(borderRect); //kleinster x-Wert (die linke Seite)
    int maxX = NSMaxX(borderRect); //gößter x-Wert (die rechte Seite)
    int minY = NSMinY(borderRect); //kleinster y-Wert (unten)
    int maxY = NSMaxY(borderRect); //größter y-Wert (oben)

    //Nun benötigen wir zwei NSBezierPath — einen für den linken/oberen Rand und einen für den rechten/unteren
    NSBezierPath *grayPath  = [NSBezierPath bezierPath];
    NSBezierPath *whitePath = [NSBezierPath bezierPath];

    //Die Rahmen links und oben sollen in grau gezeichnet werden
    [[NSColor grayColor] set];
    //Damit man den Rahmen auch gut sieht, setzen wir eine Strichstärke von 2.0
    [grayPath setLineWidth:2.0];

    //Wir beginnen unseren Pfad in der Ecke links unten und zeichnen nach links oben
    [grayPath moveToPoint: NSMakePoint(minX, minY)];
    //Linie nach links oben
    [grayPath lineToPoint: NSMakePoint(minX, maxY)];
    //von hier aus nach rechts oben
    [grayPath lineToPoint: NSMakePoint(maxX, maxY)];
    //Unser erster Pfad ist fertig, also zeichnen wir ihn mit der eingestellten Farbe
    [grayPath stroke];

    //Für die anderen beiden Seiten nehmen wir eine weiße Rahmenfarbe
    [[NSColor whiteColor] set];
    [whitePath setLineWidth:2.0];
    //wir beginnen oben rechts und zeichnen die beiden Rahmenlinien
    [whitePath moveToPoint: NSMakePoint(maxX, maxY)];
    [whitePath lineToPoint: NSMakePoint(maxX, minY)];
    [whitePath lineToPoint: NSMakePoint(minX, minY)];
    [whitePath stroke];
}
Damit haben wir schon einmal unseren äußeren Rahmen. Nun müssen wir den Hintergrund zeichnen. Hierzu erstellen wir einen NSBezierPath aus unserem backgroundRect und füllen es mit weiß. Da wir die weiße Farbe für unsere letzten beiden Linien benutzt haben, ist sie noch gesetzt. Wer eine andere Hintergrundfarbe benutzen möchte, muss sie vorher erst noch setzen.
- (void) drawRect:(NSRect)rect
{
    ...
    [[NSBezierPath bezierPathWithRect:backgroundRect] fill];
}

Nun haben wir jedoch das Problem, dass der weiße Rahmen rechts und unten mit dem Hintergrund verschmilzt. Um den Rahmen abzusetzen, ziehen wir noch eine dünne (1.0 Punkt) Linie um unseren Hintergrund. Da wir weiter oben bereits einmal grau als Zeichenfarbe verwendet haben, schreiben wir den Befehl einfach dort hinzu.

- (void) drawRect: (NSRect)rect
{
    ...
    [[NSColor grayColor] set];
    //Hier ziehen wir den Rahmen
    [[NSBezierPath bezierPathWithRect:backgroundRect] stroke];
    ...
}

Wer statt dem eingesunkenen Rahmen lieber einen hervorgehobenen haben möchte, vertauscht einfach die Rahmenfarben.
Einen stärkeren Effekt erzielt man, wenn man den oberen und linken Rahmen in schwarz statt grau zeichnet.


Ähnliche Artikel

Dein Kommentar:

Sämtliche Html-Tags werden gelöscht, der Kommentar kann mit Textile formatiert werden.
Vor dem Absenden müsst ihr euch einmal die Vorschau ansehen.