Window Resize erzeugt Grafikfehler

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

  • Window Resize erzeugt Grafikfehler

    Hallo,

    ich habe mich mal an einer eigenen OS X App versucht und habe in 2 Monaten ein Konzept sowie ein voll funktionstüchtiges Programm auf die beine gestellt.
    Währen der (closed beta), in der einige meiner Kollegen mein Programm getestet haben, wurden einige Designmängel im Userinterface entdeckt. Daraufhin
    habe ich beschlossen das Interface vollständig zu überarbeiten.

    Ich erstellte eine neues Projekt und Testete erstmal verschiedene Anordnungen. Dabei bin ich auf einige Probleme gestoßen.

    1. Beim Resize des Window entstehen Grafikfehler in der ToolBar.
    [IMG:http://www7.pic-upload.de/03.09.13/msodrz2hfjm.png]
    2. Nach dem Resize bleiben einige Grafikfehler vorhanden.
    [IMG:http://www7.pic-upload.de/03.09.13/hdu25qks5hx2.png]
    3. Beim Wechsel in eine andere Anwendung und nach dem darauf folgendem Wechsel zurück in meine Anwendung verschwinden die Fehler.
    [IMG:http://www7.pic-upload.de/03.09.13/xkmzjnzcn5b9.png]

    Ich habe mir das Programmieren mit Objektive-C selber beigebracht sowie über Bücher, Tutorials und Stanford iTunes-U erweitert, habe aber schon zu meinen Java und C# Zeiten immer Probleme mit Interface
    Geschichten gehabt. Da nach dem wechseln zu einer anderen Anwendung (in Punkt 3.) die Grafikfehler verschwinden verstehe ich nicht ganz warum
    während des Resizing und danach die Grafikfehler entstehen.

    In der NSToolbar ist eine CustomView. Damit diese in der Mitte gehalten wird sind links und rechts "Flexible Spaces" eingefügt. Die ToolbarItems werden ausschließlich
    Programmatisch erzeugt. Im Linken Teil der App ist eine NSOutlineView (SourceView) in der Mitte liegt eine NSOutlineView und Rechts ist eine CustomView die noch ausgearbeitet wird.
    Dies Statusleiste am Unteren Teil der App ist ebenfalls eine CustomView. Ich Arbeite mit Autolayout, Constraints werden lediglich im IB gesetzt. OS X 10.8.4 mit Xcode 4.6.3.

    Warum entstehen die Fehler und wie kann ich diese verhindern.

    mfg.Jan

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von jworuna ()

  • Hi,

    so ins Blaue...

    Bei eigenen (selbst gemalten) Views muss man dem Grafiksystem mitteilen, das die View neu gezeichnet werden muss. NSView hat eine Methode namens setNeedsDisplay. Dadurch erfährt das Grafiksystem, das die View neu gezeichnet werden muss und ruft die drawRect: der View auf.

    Das behebt solche Fehler dann meistens.

    Ob ein Resize erfolgt ist, bekommst über das Window Delegate mit, dann kannst du jedesmal deine Custom Views zum neu Zeichnen markieren.

    Oder setFrame: deiner Customview überschreiben

    Quellcode

    1. - (void) setFrame: (NSRect)r
    2. {
    3. [super setFrame: r];
    4. [self setNeedsDisplay: YES];
    5. }


    Das "iTunes Titelfenster" sieht aber irgendwie so aus, als würde es über den Rand eine Superview malen. Aber versuch erst mal die needsDisplay Geschichte (falls noch nicht passiert).

    Gruß
    Manfred
    Seminare, Artikel, Code. ObjectiveCeeds - alles für die Apfelzucht.
  • Hallo,

    so ins Blaue...

    Bei eigenen (selbst gemalten) Views muss man dem Grafiksystem mitteilen, das die View neu gezeichnet werden muss. NSView hat eine Methode namens setNeedsDisplay. Dadurch erfährt das Grafiksystem, das die View neu gezeichnet werden muss und ruft die drawRect: der View auf.

    Das behebt solche Fehler dann meistens.

    Ob ein Resize erfolgt ist, bekommst über das Window Delegate mit, dann kannst du jedesmal deine Custom Views zum neu Zeichnen markieren.

    Oder setFrame: deiner Customview überschreiben


    Quellcode
    - (void) setFrame: (NSRect)r
    {
    [super setFrame: r];
    [self setNeedsDisplay: YES];
    }

    Ehrlich gesagt höre ich das zum ersten Mal, dass das so praktiziert wird.
    Das System "zwingt" das View automatisch zum Neuzeichnen, wenn es sich verändert wie z.B. bei -setFrame: etc.

    Angenommen ich habe ein eigenes View mit einer Eigenschaft "Text" und setze die neu.
    Klar, dann muss mein Setter ein Neuzeichnen anstoßen.

    Aber nicht bei einem Resize des Fensters…

    Im Linken Teil der App ist eine NSOutlineView (SourceView)

    Das ist ja kein eigens erstelltes Ding und da passiert der Fehler.

    Ich denke, dass da was mit dem Autolayout nicht stimmt. Aber da kenne ich mich nicht mit aus, da ich das nicht verwende.
    Probiere es doch mal zum Test einfach mal mit -setAutoresizingMask: aus.

    Viele Grüße
  • Hallo,

    danke für die Antworten.

    Die kleinen schwarzen grafikfehler in der Toolbar habe ich durch das aufrufen der setNeedsDisplay Methode der CustomView
    in der Toolbar, entfernt. - Danke Manfred
    Die CustomView in der Toolbar wird durch ein NSToolbarFlexibleSpaceItemIdentifier am Anfang sowie am Ende der Toolbar im Mittelpunkt(Center) der Toolbar gehalten.
    Beim Resize schiebt sich dadurch die CustomView unter die NSToolbarFlexibleSpaceItemIdentifier.
    Der Fehler bei der Outlineview besteht noch, ein Aufruf von setNeedsDisplay hilft dort allerdings nicht. Ich werde es morgen mal mit setAutoResizingMask versuchen. Der Fehler wird definitiv von der CustomView mit Farbverlauf (Statusleiste) am unteren Teil der app ausgelöst. Wenn ich keine subclass für die view verwende, entsteht der Fehler nicht.

    mfg.Jan
  • Also, es sieht wie folgt aus:

    1. Ein View muss selbst bestimmen, ob und was neu gezeichnet wird. Denn nur der View kann wissen, welche Änderungen welche Bereich berührt.

    2. Soweit etwas eine Eigenschaft der Basisklasse (insbesondere NSView) ist, macht das Cocoa auch. Ändere ich etwa den Frame, so muss /intern/ NSView sagen, dass neu gezeichnet wird.

    3. Führe ich selbst Eigenschaften in einer Subklasse ein, so muss ebenfalls die Subklasse das Neuzeichnen mit needs display auslösen.

    Zusammengefasst:
    setNeedsDisplay: et al. müssen gesendet werden, aber aus der Viewklasse heraus, nicht von außen.
    Cocoa-Klassen machen das schon. Wenn nicht: Bug-Report
    Niemals sollte es erforderlich sein, außerhalb der Klasse setNeedsDisplay: zu senden.
    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"?
  • Hallo,

    @little_pixel: Mit deinem Beispiel kann ich leider nichts anfangen. Ich arbeite Ausschließlich mit dem InterfaceBuilder.
    @Amin: Danke für die Erklärung.

    Hier einmal das Bsp. Projekt. Vielleicht versteh ich da auch Grundlegend was Falsch beim Erzeugen des Interface mittels InterfaceBuilder (Wird glaub ich nicht mehr so genannt).

    mfg.Jan
  • Hallo,

    Quellcode

    1. [toolbarItem setMaxSize:NSMakeSize(CGFLOAT_MAX, 50.0)];
    2. [toolbarItem setMinSize:NSMakeSize(100.0, 50.0)];

    Das habe ich in meinem Beispiel drin.

    Das löst sofort bei Dir das Toolbar-Custom-View-Resizing-Anzeige-Dingens-Problem.
    Allerdings wirst Du dann feststellen, dass die Positionen der Elemente nicht mehr stimmen.

    Füge in der Klasse "ToolBarView" der -drawRect: Methode mal ein NSRectFill() mit roter Farbe hinzu.
    Dann wirst Du feststellen, dass Du auch nicht da zeichnest wo Du vielleicht vermutest.

    Des Weiteren brauchst Du nur die Zeile 44 auskommentieren und Deine Gnazen Probleme sind ade…

    Das Ganze sieht ein bisschen nach Gewürfelt aus :-p
    Ich habe es aber auch nur überflogen.

    Viele Grüße
  • Hallo,

    danke für die Antwort @little_pixel.
    Nach der Anpassung sind fast alle Fehler entfernt.
    Die CustomView in der Toolbar hat auf einem NSRect gezeichnet, welches 550px breit war.
    Ich dachte der übernimmt die Einstellung aus dem IB. Habe die Größe des NSRect jetzt im Code auf einen Festen wert gestellt.

    Der Fehler in der SourceView ist noch vorhanden. Außerdem ist die CustomView in der ToolBar nicht mehr im Zentrum nach dem window resize.

    //Nachtrag: CustomView ist jetzt im Center. Habe die Min und Max Size des ToolbarItem auf die Größe der CustomView gesetzt.

    Das sieht so Zusammen gewürfelt aus, weil es das auch ist. ;D
    Wie schon geschrieben, sobald irgendetwas mit UI oder Grafik auftaucht muss ich frickeln.

    //Nachtrag 2: Hab das Problem gelöst. Habe das Layout, die einzelnen Views, jetzt mit NSSplitViews aufgebaut.
    Dadurch ist auch der Letzte Fehler verschwunden.

    Ich danke allen die geholfen haben!

    mfg.Jan

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von jworuna ()