CGRect verschieben?

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • CGRect verschieben?

    Hi,
    ich versuche mich erstmals daran gezeichnete CGRects zu verschieben. Leider wird die "Szene" nicht neu gezeichnet.
    Hier erstmal der Code für die drawRect Methode:

    Quellcode

    1. ​- (void)drawRect:(NSRect)dirtyRect {
    2. NSLog(@"redraw");
    3. CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
    4. CGColorRef black = [[NSColor blackColor] CGColor];
    5. CGColorRef yellow = [[NSColor yellowColor] CGColor];
    6. CGContextClearRect(context, stab1);
    7. CGContextSetFillColorWithColor(context, black);
    8. CGContextFillRect(context, stab1);
    9. NSLog(@"%f",stab1.origin.x)
    10. }

    Stab1 wird in awakeFromNib folgendermaßen initialisiert:

    Quellcode

    1. ​stab1 = CGRectMake(bounds.origin.x + 100, bounds.origin.y + 50, 5, 200);

    Nun soll das komplette Rechteck auf die x-Koordinate "5" verschoben werden.
    Dazu habe ich die Methode "move:(int)d", der Integer "d" gibt wieder, welches Rechteck verschoben werden soll.
    Die Methode "move" wird über eine andere Klasse aufgerufen, was soweit auch funktioniert.
    Hier die Move-Methode:

    Quellcode

    1. ​- (void)move:(int)d{
    2. if (d==1) {
    3. stab1.origin.x = 5;
    4. [self setNeedsDisplay:YES];
    5. NSLog(@"test");
    6. }

    Zuerst habe ich das "setNeedsDisplay" vergessen und dachte, dass damit das Problem gelöst wäre, allerdings funktioniert es immer noch nicht.
    Wo liegt bei der Sache mein Denkfehler? Die Konsole gibt genau die Parameter aus die ich gesetzt habe, allerdings wird das Rect nicht mit den neuen Parametern gezeichnet :(.

    Gruß
    Noah
  • Erstmal muss drawRect den kompletten Inhalt malen. Du müsstest also zumindest mal schauen ob Du backgroundColor gesetzt hast, weil Du sonst den kompletten UIView selber füllen solltest. Schau auch mal ob Du opaque auf YES setzt. Nur wegen der Performance.

    Zweitens sehe ich nur ein schwarzes fFillRect, kein gelbes.

    Drittens dient CGContextClearRect nicht zum zeichnen sondern nur zur Initialisierung eines BitMap oder Window Contexts.
    Steht zumindest in der Doku.

    Wenn man transparparent löschen will benutzt man FillRect und [UIColor clearColor]
  • Oh sorry, Gelb war nur ein Überbleibsel, welches ich vergessen hatte zu löschen.
    Ich lasse nur ein Rect zeichnen weil ich probieren wollte, wie das mit dem verschieben funktioniert.
    Die View ändert nichts mehr nachdem ich das erste mal gezeichnet habe.
  • pmau schrieb:

    Drittens dient CGContextClearRect nicht zum zeichnen sondern nur zur Initialisierung eines BitMap oder Window Contexts.
    Steht zumindest in der Doku.

    Hä? Nee, da steht, dass die Funktion ein Rechteck löscht. Der Draw-Code ist etwas wirr, sollte aber was tun.

    Zurück zur Frage: Eigentlich sollte der Mechanismus so wie du es dir vorstellst funktionieren. Was gibt das Log denn aus? Wo ist "stab1" definiert? Kannst du ein Testprojekt hochladen?
    Multigrad - 360°-Produktfotografie für den Mac
  • Das ist also nicht Dein drawRect code?
    Wie soll man Dir dann helfen.

    Im Moment macht Dein View nichts anderes als ein schwarzes Rechteck zu füllen. Zeile 7 und 8.
    Was soll man da sehen?

    Was ist mit der backgroundColor?
  • mattik schrieb:

    Hä? Nee, da steht, dass die Funktion ein Rechteck löscht. Der Draw-Code ist etwas wirr, sollte aber was tun.

    Zurück zur Frage: Eigentlich sollte der Mechanismus so wie du es dir vorstellst funktionieren. Was gibt das Log denn aus? Wo ist "stab1" definiert? Kannst du ein Testprojekt hochladen?


    Zitat

    However, you should not use this function in contexts other than window or bitmap contexts.
  • Das ist mein Code! Ich habe nur davor eben 2 Rechtecke Zeichnen lassen, eines gelb und eines schwarz.
    Ich ändere doch auf Knopfdruck den Ursprung des Rechtecks und sage dann bescheid, dass neu gezeichnet werden soll.
    Werde gleich das ganze Projekt hochladen. Ich habe versucht die Türme von Hanoi nachzuprogrammieren.
    Wir fangen im Unterricht mit gerade mit Rekursion an (da programmieren wir zwar in Java aber persönlich gefällt mir halt Objective-C besser) und da dachte ich, dass das ein gutes Beispiel zum Üben wäre.
    Allerdings scheitere ich schon an der grafischen Darstellung. Für die "Logik" hinter der Grafik würde ich schon ungefähr wissen, wie ichs anstelle.
  • Puh, da gibt es soviel zu sagen:

    Du hattest die "stab" und "boden" NSRect als global deklariert und jedes mal den header importiert.
    Die gehören aber als Property an den NSView.

    Den "graphics" NSView habe ich als Outlet im comtroller deklariert und damit verbunden.
    Du willst nicht jedes mal einen neuen anlegen der gar nicht verbunden war.
    Dateien
  • Okay, habs mir angeschaut und konnte meine Fehler nachvollziehen.
    Vielen Dank für die Erklärung und die Verbesserung, ist mir ne große Hilfe.
    Bin halt eben doch noch ein Anfänger :)

    Gruß Noah
  • pmau schrieb:

    mattik schrieb:

    Hä? Nee, da steht, dass die Funktion ein Rechteck löscht. Der Draw-Code ist etwas wirr, sollte aber was tun.

    Zurück zur Frage: Eigentlich sollte der Mechanismus so wie du es dir vorstellst funktionieren. Was gibt das Log denn aus? Wo ist "stab1" definiert? Kannst du ein Testprojekt hochladen?


    Zitat

    However, you should not use this function in contexts other than window or bitmap contexts.


    Ja, das steht in der Discussion, unter anderem. Aber wie schließt du daraus, dass die Funktion "nur zur Initialisierung eines BitMap oder Window Contexts" da ist? Sorry, das ist Quatsch. Das heißt erstmal nichts anderes, als dass die Funktion nur für solche Kontexte verwendet werden sollte - was hier ja der Fall ist. In der Doku steht als Funktionsbeschreibung erstmal: "Paints a transparent rectangle" - und genau das tut sie auch.

    Multigrad - 360°-Produktfotografie für den Mac
  • Ein Graphics Context besteht aus mindestens zwei Teilen. Einen Speicherbereich in den gerastert wird und einen OpenGL Teil der die ganzen Layer als Texturen auf den Bildschirm bringt.
    CoreGraphics arbeitet prinzipiell erstmal mit BitMap Contexten die dann auf die GPU hochgeladen werden.
    Dort geschieht das ganze Blending, Transform, etc.

    Bei jeder "drawRect" Operation wird irgendwo vom Layer "drawInConext" aufgerufen,
    Da wird gerastert und anschliessend auf die GPU hochgeladen.

    Die Funktion "CGContextClearRect" überschreibt den darunterliegenden BitMapContext mit Nullen.
    Durch die Markierung mit "Copy On Write" wird der alte dabei sogar kopiert, da dort die Textur erstmal noch dranhängt.

    Da aber die Representation von "schwarz", "transparent" oder "leer" (wie immer Du das nennen magst) vom ColorSpace und Pixelformat und Ähnlichem abhängt,
    ist "CGContextClearRect" streng genommen eben kein Draw Befehl.

    Deshalb soll man ihn eben nicht als solchen benutzen sondern ein "FilllRect' mit "clearColor" benutzen.
    Wenn man natürlich weiss das man den kompletten BackingStore einfach zurücksetzen will kann man das natürlich tun.

    Rein von der API her ist CGContextClearRect aber keine Zeichenoperation.
  • Ein CGContext ist erst einmal nur eines: Eine Abstraktion. Ein GCContextRef ist ein opaker Datentyp, bei dem man gerade keine Vermutungen oder Annahmen darüber anstellen sollte, wie er intern aufgebaut ist. Es gibt einen OpenGL-basierten Renderer, es gibt aber auch andere. Es können Layer im Compositing dazwischen hängen, muss aber nicht so sein. Solche Annahmen können einem ganz böse auf die Füße fallen. Apple hat das Renderingsystem in den letzten Jahren mehrfach geändert, wer da von irgend einem spezifischen internen Aufbau ausgeht hat dann u.U. schlechte Karten.

    Aber wieso sollte das alles irgend einen Einfluss darauf haben, was CGContextClearRect tut? Warum sollte das begründen, dass es keine Zeichenoperation ist? CGContextClearRect ist eine Zeichenoperation - genau wie andere Zeichenoperationen. Was ist denn an "Paints a transparent rectangle" so zweideutig? Und warum steht sie wohl unter "Painting Paths"? Kurz: Wie kommst du auf die Idee, dass das Ding etwas anderes tun sollte als es dokumentiert ist?

    Wo steht, dass CGContextClearRect Nullen schreibt? Hast du da eine Quelle?
    Multigrad - 360°-Produktfotografie für den Mac
  • Die sourcen von GNUstep

    svn.gna.org/svn/gnustep/libs/q…k/Source/CABackingStore.m

    Quellcode

    1. #if GNUSTEP
    2. #warning Opal bug: context should be cleared automatically
    3. #if 0
    4. CGContextClearRect (context, CGRectInfinite);
    5. #else
    6. #warning Opal bug: CGContextClearRect() permanently whacks the context
    7. memset (CGBitmapContextGetData (context),
    8. 0, bitmapBytesPerRow * pixelsHigh);
    9. #endif
    10. #endif
    11. return context;
    12. }
    Alles anzeigen


    CGContextClearRect ist eine Optimierung für CGBitMapContext basierte CGContextRef.
    Damit eben genau nur das memset ausgeführt wird.

    Bei alle anderen CGConntextRef Arten funktioniert diese Methode nicht.
    Zum Beispiel bei einem PDF Context.

    Die Methode geht eben genau davon aus das es sich um einen CGBitMapContext handelt bei dem "Alles auf Null" eben schwarz (ohne Alpha Channel) oder komplett transparent (mit Alpha Channel bedeutet.)

    Aber Du darfst gerne weiter argumentieren. Ich sage eben, dass Apple selbst sagt, dass diese Methode ein Spezialfall ist und man sie deshalb nicht universal benutzen soll. Du sagst selber, dass der interne Aufbau keine Rolle spielen soll. Also heisst die Lösung CGContextFillRect mit clearColor.

    Die Methode ist eben wie dokumentiert keine unverselle Zeichenmethode.

    Es sei denn, wie Du selber sagst, Du triffst Annahmen über Deine Umgebung.
    Und genau dagegen habe ich argumentiert.

    Aber sei's drum.
    Gute Nacht.
  • Und wo ist jetzt deine Quelle, dass darin ein memset passiert? Und dass das irgendwas mit Bitmaps zu tun hätte? Das steht da nicht. Das nimmst du nur an.

    Es ist aber nicht so. CGContextClearRect ist ein ganz normaler Zeichenbefehl. U.a. einer, der den aktuellen Clipping Path berücksichtigt - wie alle anderen Zeichenbefehle auch. Wie soll das mit einem primitiven memset funktionieren? Ich mache da keine Annahmen, ich verwende den Befehl wie er dokumentiert ist. Wie ein ganz normaler Zeichenbefehl, mit den dokumentierten Einschränkungen. Für den im OP genannten Fall ist er komplett legitim und richtig. Warum sollte die Lösung fillRect mit clearColor sein, wenn es für genau diesen Fall eine Funktion gibt? Abgesehen davon bringt ein fillRect mit clearColor nicht immer das gewünschte Ergebnis - z.B. wenn der Blend Mode nicht stimmt.

    Multigrad - 360°-Produktfotografie für den Mac