Announcement

Collapse
No announcement yet.

Überlagerte PictureBoxes einem Panel hinzufügen...ohne Flackern

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Überlagerte PictureBoxes einem Panel hinzufügen...ohne Flackern

    Hallo zusammen,

    nachdem ich nun seit ca. 6 Stunden vergeblich versucht habe das Problem zu lösen, möchte ich mein Problem einmal hier schildern.

    Die Anforderung:
    Nach einem Klick in eine Listbox soll eine PictureBox einem bestehenden Panel hinzugefügt werden. Die PictureBoxes werden dabei dem Namen nach sortiert und gleichartige Pictureboxes werden überlappend dargestellt.
    Etwa wie im Anhang Karten_sortiert.jpg

    Das Problem:
    Da die PictureBoxes sortiert werden, werden diese von oben nach unten gezeichnet.
    Genauer: Die neuste PictureBox wird dem Panel hinzugefügt und über eine Sortiermethode werden die Positionen der PictureBoxes bestimmt, beginnend bei der ersten (oben links).
    Dabei werden leider alle folgenden PictureBoxes unter die jeweils vorhergehenden PictureBoxes gezeichnet. Etwa wie im Anhang Karten_falsch-sortiert.jpg

    Um die PictureBoxes dann wieder sichtbar zu machen, verwende ich die Methode "SendToFront". Dieser Aufruf führt leider zu dem im Topic beschriebenen Flackern.

    Der Code:
    Hinweise:
    cardContainer ist das Panel, auf dem die PictureBoxes sortiert werden
    Die Pfeile (z.B.// -->1) markieren meine vergeblichen Versuche, das Flackern zu unterdrücken.
    Code:
    // Karten neu anordnen
    int cardCount = 0;
    int cardTypeCount = 0;
    // this.SuspendLayout();          // -->1
    // cardContainer.SuspendLayout(); // -->2
    foreach (string card in cardObjects)
    {
        foreach (Control ctl in cardContainer.Controls)
        {
            if (ctl.Name == card)
            {
                // Karte positionieren entsprechend der vorhandenen Anzahl in diesem Panel
                // ctl.SuspendLayout(); // -->3
                // ctl.Hide();          // -->4
                ctl.Location = new System.Drawing.Point(10+ cardTypeCount * 140, 10 + 20 * cardCount);
                cardCount++;
                // TODO: Es flackert...
                ctl.BringToFront();
            }
        }
        cardCount = 0;
        cardTypeCount++;
    }
    
    // Jetzt alle Karten anzeigen
    foreach (Control ctl in cardContainer.Controls)
    {   
        // ctl.Show();          // -->4
        // ctl.ResumeLayout();  // -->3
    }
    // cardContainer.ResumeLayout(); // -->2
    // this.ResumeLayout();          // -->1
    Die Vergeblichen Versuche:
    Meine Versuche, das Problem zu lösen habe ich im obigen Code markiert.
    -->1:
    SuspendLayout() "Unterbricht vorübergehend die Layoutlogik für das Steuerelement." Auf dem Formular ausgeführt ändert es nichts am Flackern der Picturebox.

    -->2:
    SuspendLayout() auf dem Panel ausgeführt ändert ebenfalls nichts am Flackern.

    -->3:
    SuspendLayout() auf der PictureBox ausgeführt hilft auch nicht. Auch die Kombination aus allen bewirkt nichts.

    -->4:
    Ein Hide() auf die PictureBox führt natürlich ebenfalls zu einem Flackern, da nun alle PictureBoxes ausgeblendet - sortiert - eingeblendet werden. Hier muss es logischerweise flackern, auch wenn es ein wenig angenehmer wirkt, weil die BringToFront-PictureBox nicht immer in den Vordergrund gezeichnet wird.

    DoubleBuffer:
    Auch das aktivieren des DoubleBuffers auf der Form über den Code
    Code:
    this.SetStyle(ControlStyles.DoubleBuffer |
                 ControlStyles.UserPaint |
                 ControlStyles.AllPaintingInWmPaint,
                 true);
    this.UpdateStyles();
    führte nicht zum erhofften Ergebnis.

    Ich wäre für jeden Hinweis dankbar, ich habe keine Idee mehr, was ich noch anders machen kann.

    Torsten
    Attached Files
    Zuletzt editiert von staratnight; 28.06.2008, 11:43.

  • #2
    Hallo Torsten,

    füge die Pictureboxen doch einfach in umgekehrter Reihenfolge (also von unten nach oben) hinzu.

    Oder

    Zeichne auf einem unsichtbaren Card Container. Wenn alles an seinem Platz ist, packst Du den Card Container auf die Form und zeigst ihn an.

    Oder ähnlich.

    Zeichne die einzelnen Kartenstapel auf jeweils einem zunächst unsichtbaren Panel. Wenn alles an seinem Platz ist, packst Du die Panel auf die Form und zeigst sie an. Die Panel würden Dir auch beim Verechieben von Kartenstapeln helfen.

    Oder

    Vergiss die Pictureboxen und zeichne die Karten selbst per GDI+. Ist ein bisschen mehr Arbeit aber flexibler und schneller.

    Gruss
    Peter
    Zuletzt editiert von Peter Enz; 30.06.2008, 09:06.

    Comment


    • #3
      Hallo Peter,

      schonmal Danke für deine Antwort.

      Ich habe versucht auf einen zweiten Container zu zeichnen, aber irgendwie wollte mir das nicht recht gelingen. Eine Kopie des Containers mit allen abhängigen Controls konnte ich über Reflection schon erreichen. Wenn ich dann auf der Kopie die Controls positioniere, funktioniert das auch. Wenn ich die Kopie aber dann wieder dem Original zuweisen möchte, gehen die Positionen aller Controls verloren...

      Ich werde mich bei nächster Gelegenheit mit der GDI+ auseinandersetzen. Die ist für diesen Zweck wahrscheinlich tatsächlich am besten geeignet...

      Gruß,
      Torsten

      Comment


      • #4
        Originally posted by staratnight View Post
        Eine Kopie des Containers mit allen abhängigen Controls konnte ich über Reflection schon erreichen.
        Wozu Reflection?

        Originally posted by staratnight View Post
        Ich werde mich bei nächster Gelegenheit mit der GDI+ auseinandersetzen. Die ist für diesen Zweck wahrscheinlich tatsächlich am besten geeignet...
        Ja, kann ich Dir nur empfehlen. Ist auch nicht so sehr kompliziert. Viel Erfolg.

        Gruß
        Peter

        Comment


        • #5
          Originally posted by Peter Enz View Post
          Wozu Reflection?
          Weil ich eine "echte" Kopie der Controls brauche, sonst habe ich ja wieder nur eine Referenz. Damit verschiebe ich ja trotzdem die Controls im Vordergrund und hab das Problem des Flackerns damit weiterhin...oder hab ich da was falsch verstanden? *grübel*

          Über Reflection erhalte ich alle Eigenschaften der Controls, so dass ich diese mit wenig Code kopieren kann. Leider gibt es ja kein "Clone" auf Controls.

          Comment


          • #6
            [QUOTE=staratnight;170849]Weil ich eine "echte" Kopie der Controls brauche, sonst habe ich ja wieder nur eine Referenz. [QUOTE]

            Wozu brauchst Du eine Kopie der Controls? Du willst doch nur Kartenstapel anzeigen. Das sind 1 bis n Pictureboxen. Die packst Du wie gesagt auf ein unsichtbares Panel. Wenn fertig, schiebst Du das Panel an die richtige Stelle und machst es dann sichtbar. (Visible=true Dabei sollten doch auch keine Positionen verrutschen? Das Panel das vorher an der Position lag, machst Du unsichtbar und fertig.

            Oder übersehe ich da jetzt was?

            Gruß
            Peter

            Comment


            • #7
              Originally posted by Peter Enz View Post
              Oder übersehe ich da jetzt was?
              Wahrscheinlich nicht. Ich war eher zu vertieft in das Problem, dass ich die einfachsten Lösungen nicht gesehen habe.

              Mein Gedankengang war es, zum Zeitpunkt der Sortierung ein zweites, nicht sichtbares Panel anzulegen, darauf zu sortieren und das dann wieder dem ursprünglichen, sichtbaren Panel zuzuweisen. Um so vorzugehen benötige ich die echte Kopie.
              Es spricht aber überhaupt nichts dagegen, permanent zwei Panels vorrätig zu halten, die ich beide mit Karten fülle und beide abwechselnd im Hintergrund sortiere...also so, wie du es vorgeschlagen hast.

              Alternativ - und da hilft mir ein Umbau, den ich gerade ohnehin vornehme - kann ich die Karten selbst in einem eigenen Container vorrätig halten und die Panel immer wieder neu mit Pictureboxes bestücken und abwechselnd anzeigen.
              Mal sehen, wie gut der GarbageCollector damit klar kommt ;-)

              Danke für deine Gedankenanstöße. Wenn ich soweit bin, dass ich das Anzeigeproblem wieder angehen kann (nach der Codeumstrukturierung), geb ich bescheid, wie es geklappt hat.

              Gruß,
              Torsten

              Comment


              • #8
                Das Problem ist gelöst.
                Das Flackern kam nicht durch die Picturebox, sondern durch dir darunterliegenden Panels.

                Sobald die Picturebox auf ein Panel (egal ob Panel oder SplitPanel) gemalt wird, flackert es bei der Anzeige.
                Wird die Positionierung aber nicht auf einem Panel, sondern direkt auf dem Form durchgeführt, flackert das Malen der Panels nicht.

                Bisher habe ich die Sortierung der Karten über die Panels durchgeführt. Dies erfolgt - nach der Coderestrukturierung - nun in internen Listen. Ich benötige die Panels also nicht mehr und habe das Problem dadurch umgangen.

                Wichtig:
                Erst mit aktiviertem DoubleBuffer flackert das Malen der PictureBoxes nicht mehr.

                Comment

                Working...
                X