Programmieren mit Swift - Für macOS und iOS
Programmieren mit Swift - Für macOS und iOS
Zeichnen mit NSView, Teil 2

Die nächste Aufgabe soll sein, ein Schachbrettmuster von acht mal acht Feldern zu zeichnen. Die Felder selbst sollen jeweils ein Achtel der Seitenlänge des View haben. So wird sichergestellt, dass der View immer komplett ausgefüllt wird, selbst wenn er nicht komplett quadratisch ist.
Für eine Zeile mit schwarzen und weissen Felder müsste der Code so aussehen:
- (void)drawRect:(NSRect)dirtyRect
{
    NSRect bounds = [
self bounds];

    float fieldWith = bounds.size.width / 8.0;
    float fieldHeight = bounds.size.height / 8.0;

    for (int z = 0; z < 8; z++)
    {
        NSRect aRect = NSMakeRect(fieldWith * z, 0, fieldWith, fieldHeight);

        // Schwarz oder Weiss ??
        if (z % 2 == 0)
        {
            [[NSColor blackColor] set];
        }
        else
        {
            [[NSColor whiteColor] set];
        }

        // Rechteckt zeichen
        [NSBezierPath fillRect:aRect];
    }
}
Möchte man dann eine NSView mit acht mal acht Feldern, ist nur eine kleine Erweiterung nötig.
- (void)drawRect:(NSRect)dirtyRect
{
    NSRect bounds = [
self bounds];

    float fieldWith = bounds.size.width / 8.0;
    float fieldHeight = bounds.size.height / 8.0;

    for (int x = 0; x < 8; x++)
    {
        for (int z = 0; z < 8; z++)
        {
            NSRect aRect =
             NSMakeRect(fieldWith * z, fieldHeight * x, fieldWith, fieldHeight);

            // Schwarz oder Weiss ??
            if ( (z+x) % 2 == 0)
            {
                [[NSColor blackColor] set];
            }
            else
            {
                [[NSColor whiteColor] set];
            }

            // Rechteckt zeichen
            [NSBezierPath fillRect:aRect];
        }
    }
}
stacks_image_A07FFFDA-2EEC-4620-81C2-1F2D32F4F048
Dieses Beispiel soll aber keineswegs dem Schachspiel dienen, sondern die Frage beantworten, wie sich Objekte verhalten, die übereinander liegen. Objekte, die teilweise transparent sind.

Zuerst soll das Schachbrett aber einen dünnen Rahmen bekommen. Da es aber den View komplett ausfüllt, ist für einen Rahmen um das Schachbrett herum kein Platz mehr. Sie müssen also ein Rechteck über das Schachbrett zeichnen. Aber kein gefülltes Rechteck, denn das würde ja alle Felder überdecken. Erweitern Sie die drawRect-Methode um folgenden Code.
[[NSColor brownColor] set];
NSBezierPath *aPath = [NSBezierPath bezierPathWithRect:bounds];
[aPath setLineWidth:5];
[aPath stroke];
Im Gegensatz zu den bisherigen Anweisungen wird hier keine Klassenmethode aufgerufen, sondern tatsächlich ein NSBezierPath Objekt erzeugt. Dem Objekt wird nachträglich die Linienstärke 5 zugewiesen und mit stroke wird das Objekt veranlasst, sich selbst zu zeichnen. Die Nachricht fill an das selbe Objekt würde wieder ein ausgefülltes Rechteck zeichnen.
stacks_image_E4576BED-D7CD-4DCF-8153-F453910867C4
Als nächstes soll das Schachbrett mit einem roten, teilweise transparenten Kreis überlagert werden.

Dafür sind drei Schritte nötig. Zuerst benötigt man eine halbtransparente Farbe. Da sich so ein Farbton nicht in der Liste der vordefinieren Farben befindet, muss man ihn selbst mischen.
Anschliessend benötigt man ein Rechteck, mit dem die Abmessungen des Kreises bestimmt werden können. Um in diesem Rechteck dann einen kreisförmigen Pfad zu zeichnen, ist eine weitere Anweisung nötig.
NSColor *transRed = [NSColor colorWithDeviceRed:1.0 green:0 blue:0 alpha:0.5];
[transRed set];

NSRect circleRect = NSMakeRect(bounds.origin.x +
20, bounds.origin.y + 20,
 bounds.size.width -
40, bounds.size.height -40);

NSBezierPath *circlePath =[NSBezierPath bezierPathWithOvalInRect:circleRect];
[circlePath fill];
Beachten Sie auch, wie sich der Kreis verhält, wenn Sie das Fenster skalieren.
stacks_image_BEC47B3C-409A-4C0F-8A15-636B524D4483
Mit Kreisen und Rechtecken kann man zwar schon eine ganze Menge darstellen, alle grafischen Anforderungen erfüllen diese Formen aber nicht. Zum Glück kann man aber auch einen NSBezierPath mit frei definieren Punkten festlegen und so jede mögliche Form zeichnen.
NSPoint p1 = NSMakePoint(bounds.size.width /2, 10);
NSPoint p2 = NSMakePoint(
10, bounds.size.height/2);
NSPoint p3 = NSMakePoint(bounds.size.width /
2, bounds.size.height - 10);
NSPoint p4 = NSMakePoint(bounds.size.width -
10, bounds.size.height /2);

NSBezierPath *shape = [NSBezierPath bezierPath];
[shape moveToPoint:p1];
[shape lineToPoint:p2];
[shape lineToPoint:p3];
[shape lineToPoint:p4];
[shape closePath];
[shape setLineWidth:
4];

[[NSColor yellowColor] set];
[shape fill];
[[NSColor blueColor] set];
[shape stroke];
stacks_image_00CD887E-20E4-417F-A1DC-60B931A2B043