Picturebox vor Flowlayoutpanel

  • VB.NET

Es gibt 185 Antworten in diesem Thema. Der letzte Beitrag () ist von Schmandal.

    Das alles war auf meine vorher genannte Paint Methode bezogen. Wenn ich Deine und Rods Beiträge richtig verstanden habe, ist die Paint Methode wohl nicht die beste Lösung sowas zu realisieren. Ich werde mir die Projekte nochmals genauer anschauen und dann versuchen die Karten aus den Pictureboxen zu entfernen und es komplett mit Ownerdrawing zu erledigen. Ich bin mir trotzdem noch unsicher wegen der vielen verschiedenen Lösungswege, aber vllt. erkenne ich dann ja das Positive daran (Owner Drawing / Ownerdrawing) ;)

    Schmandal schrieb:

    Wenn ich Deine und Rods Beiträge richtig verstanden habe, ist die Paint Methode wohl nicht die beste Lösung sowas zu realisieren.
    Versteh ich nicht.
    Die Paint-Methode - also die Behandlung des Paint-Events ist der Kern des OwnerDrawing-Ansatzes.
    Und den OwnderDrawing-Ansatz halte ich für den besten.

    Ist zunächstmal anspruchsvoller zu programmieren, aber das naive "picturebox hinmachen, picturebox wegmachen" zieht allerlei Folge-Probleme nach sich, die sich bei OwnerDrawing fast von selbst auflösen.
    Und somit ist OwnDrawing letztendlich auch garnet schwieriger als "picturebox hinmachen, picturebox wegmachen".

    ErfinderDesRades schrieb:

    Versteh ich nicht.


    Ach komm, hör doch nicht auf den Mist den ich schreibe ;). Ich komme, wie eingangs erwähnt, nicht mit den verschiedenen Begriffen klar, was Grafiken und Zeichnen betrifft. Bis auf die Karten nutze ich schon die Paint Methode. Habe für die Zählung der Punkte auch eine Klasse geschrieben, die rechnet und sich mit dem Server austauscht. Prüfe bei jedem Zug natürlich auf dem Server ob er machbar ist, und rechne auch noch in VB und vergleiche. Die Punkte in Ihren formschönen Kreisen zeichne ich dann auf das Brettchen.

    Schmandal schrieb:

    Bis auf die Karten nutze ich schon die Paint Methode.
    Aber genau da wäre sie angebracht. Wenn Du natürlich im Paint-Event des Hauptfensters selbst alle Karten malen willst, wirst Du nicht froh werden.
    Löse das objektorientiert:
    Mach Dir eine Karten-Klasse, wenn Du sie nicht schon hast. Gib dieser Klasse eine Paint-Prozedur, die nix anderes tut, als sich selbst zu zeichnen. Erforderliche Informationen wäen da nur die Karte selbst, also Farbe und Wert (Pik-Dame oder Schell-Lusche) und die Position. Male z.B. ein Bitmap-Objekt an die entsprechende Position.
    Im Paint-Event des übergeordneten Fensters rufst Du einfach die Paint-Routine der vorhandenen und darzustellenden Karten-Instanzen auf und feddich.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Also ich bin mir ein wenig unsicher, ob ich das ganze richtig angehe. Ich habe wie gesagt, ein Spielbrett und untereinander die 6 Reihen, in die die Karten gelegt werden. Die meisten Karten hole ich vom Server ab und packe sie in eine Liste.

    Jetzt habe ich noch folgendes gemacht:

    VB.NET-Quellcode

    1. Option Strict On
    2. Public Class Cards
    3. Public Property Image As Image
    4. Public Property x As Integer
    5. Public Property y As Integer
    6. Public Property cardname As String
    7. Public Function PaintCard(cname As String, xcoord As Integer, ycoord As Integer) As Boolean
    8. AddHandler game.brett.Paint, AddressOf DrawMe
    9. x = xcoord
    10. y = ycoord
    11. cardname = cname
    12. For Each muh In game.MImages
    13. If muh.Name & ".png" = cname Then
    14. Image = muh.Image
    15. Else
    16. End If
    17. Next
    18. game.brett.Invalidate()
    19. Return True
    20. End Function
    21. Public Sub DrawMe(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs)
    22. e.Graphics.DrawImage(Image, x, y, 100, 100)
    23. End Sub
    24. End Class


    Wenn nun eine Karte gespielt wird, rufe ich die Funktion auf:

    VB.NET-Quellcode

    1. Dim instance As New Cards()
    2. instance.PaintCard("kartenname", 100, 100)


    Ist das soweit sinnvoll? Die Koordinaten muss ich ja trotzallem pro Karte immer ausrechnen und falls eine Karte vom Brett entfernt wird, ist der Platz für eine andere ja wieder frei.

    Schmandal schrieb:

    Ist das soweit sinnvoll?
    Nicht ganz.
    Die Klasse Cards darf nix wissen von game.brett und game.MImages. Gib ihr kein Pain-Event, sondern eine Draw-Prozedur, der Du das Graphics-Objekt als Parameter übergibst.
    Eine Funktion, die nur True zurückgibt, taugt nix, mach da ne Sub draus.Das Bild selbst übergib im Konstruktor.
    Wenn Du die Karten später bewegen willst, übergib die Koordinaten an die Draw-Prozedur direkt.Die Instanz invalidisieertr kein äußeres Objekt. So etwa:

    VB.NET-Quellcode

    1. Public Class Cards
    2. Private Image As Image
    3. Public Property x As Integer
    4. Public Property y As Integer
    5. Public Property cardname As String
    6. Public Sub New(cname As String, img As Image, xcoord As Integer, ycoord As Integer)
    7. x = xcoord
    8. y = ycoord
    9. cardname = cname
    10. Image = img
    11. End Sub
    12. Public Sub DrawMe(g As Graphics)
    13. g.DrawImage(Image, x, y, 100, 100)
    14. End Sub
    15. Public Sub DrawMe(g As Graphics, xx As Integer, yy As Integer)
    16. x = xx
    17. y = yy
    18. g.DrawImage(Image, xx, yy, 100, 100)
    19. End Sub
    20. End Class
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ach super! Vielen Dank. Wenn man es einmal verstanden hat, macht es iwie Sinn :). Da ich ja derzeit noch mit png's arbeite. Gibt es eine Möglichkeit das Bild direkt in ein BMP umzuwandeln und macht das überhaupt Sinn wegen der Geschwindigkeit? Ich könnte natürlich das Bild nochmal als Bitmap speichern, aber das ist glaube ich überhaupt keine gute Idee.

    Ich frage wegen: Additional information: Ein Grafikobjekt kann nicht aus einem Bild mit einem indizierten Pixelformat erstellt werden.

    Schmandal schrieb:

    indizierten Pixelformat
    OK. Die Bilder musst Du zunächst umkopieren:

    VB.NET-Quellcode

    1. Dim bmpIndexed = New Bitmap("C:\test\8bpp.tif")
    2. Dim bmp = New Bitmap(bmpIndexed.Width, bmpIndexed.Height, Imaging.PixelFormat.Format32bppArgb)
    3. Using g = Graphics.FromImage(bmp)
    4. g.DrawImage(bmpIndexed, 0, 0)
    5. 'bmp.Save("c:\temp\32bpp.png", Imaging.ImageFormat.Png)
    6. End Using
    7. Me.BackgroundImage = bmp ' verwenden

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Alles klar, das klappt wunderbar. Auch wenn es langsam peinlich wird, aber ich schaffe es auf keiner Picturebox noch sonst iwo die Größe des Bildes zu ändern :(. Also meine Angaben zu Width und Height scheinen keine Auswirkungen zu haben. Habe nun alle Möglichkeiten durch, aber die Bilder bleiben immer alle in Originalgröße.

    Schmandal schrieb:

    alle Möglichkeiten durch
    Offensichtlich nicht.

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private bmp As Bitmap
    3. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. bmp = New Bitmap("C:\Temp\Test.png")
    5. PictureBox1.Invalidate()
    6. End Sub
    7. Private Sub NumericUpDown1_ValueChanged(sender As Object, e As EventArgs) Handles NumericUpDown1.ValueChanged
    8. PictureBox1.Invalidate()
    9. End Sub
    10. Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
    11. If bmp Is Nothing Then
    12. Return
    13. End If
    14. Dim x = 10 + CInt(Me.NumericUpDown1.Value)
    15. e.Graphics.DrawImage(bmp, New Rectangle(0, 0, x, x))
    16. End Sub
    17. End Class
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ach super, vielen Dank! Dadurch konnte ich nun schon alles anpassen, was das Interface angeht. Nun würde mich nur noch interessieren, wie man das geschickterweise mit den Kartenanordungen machen sollte.

    Bei den Karten an sich, brauche ich ja praktisch nur noch die Kartenid, die ich ausspielen will. Doch müste ich ja trotzdem jede Karte einzen zeichnen und überprüfen?

    Mal angenommen in eine Reihe passen 10 Karten nebeneinander. Das kann ich ja mit der Breite und den Coords lösen. Wenn nun aber eine weitere dazu kommt, so müsste ich ja alle Karten mehr zusammenrücken und alle neu zeichnen, richtig? Wenn dann aus dieser Reihe auf einen Schlag 5 Karten wegfallen würden, müsste ich auch alles erneut rechnen und zeichnen. Die Koordinaten würde ich, wenn ich alles nun richtig verstanden habe alle nur an die Draw Prozedur weitergeben?

    In Kürze: Ich muss für alle Karten ständig alle Koordinaten berechnen und weitergeben? Ich frage nur, weil es irgendwie viel aufwendiger zu sein schien, als der FlowLayoutPanel Ansatz :).

    Schmandal schrieb:

    ständig alle Koordinaten berechnen
    Das ist eine Frage der Organisation.
    Du hast iwo eine List(Of Cards) und Du machst Dir einfach eine DrawAllCards()-Routine. Dort per For Each durchgehen und die Koordinate der nächsten Karte per Offset zur letzten Karte berechnen.
    Und für die Zukunft:
    Gib Deinen Karten ein Deckblatt, da kannst Du sie auch anders herum zeichnen (also die Rückseite).
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ok. Ich habe gerade die Routine erstellt und das Zeichnen der Karten funtioniert wunderbar und geht recht fix :). Ich habe den Karten auch ein Deckblatt verpasst. Es gibt ja einen Nachziehstapel, bei dem die Karten andersherum liegen.

    Was ich noch net ganz blicke @ Offset: Wenn ich 4 Karten nebeneinander habe und es kommen beim nächsten Zug 3 weg und eine wieder dazu. Wie kann ich das in einem Rutsch mit Offsets berechen, oder muss die Routine dazu 4 bzw. sogar 5 mal durchlaufen werden? Ich hoffe, dass Du verstehst wie ich das meine :)
    Vielleicht machst Du den Offset von der Anzahl der Karten abhängig. Wenn es schnell genug geht, male immer alle Karten neu.
    Vielleicht kannst Du auch die Größe des Bildes von der Anzahl abhängig machen, dann gib den Karten noch ne Property Zoom.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hm, alles hat soweit wunderbar funktioniert, bis auf eine kleine Sache. Alle Bildchen sind nun extrem unscharf und wenn ich ehrlich bin, keine Ahnung warum das so ist.

    Habe folgende sub:

    VB.NET-Quellcode

    1. Public Sub paintbyname()
    2. For Each mole In Cartographer
    3. For Each muh In MyImages
    4. If muh.Name & ".png" = mole Then
    5. bmpIndexed = New Bitmap(sAppPath & "karten\" & mole)
    6. bmp = New Bitmap(bmpIndexed.Width, bmpIndexed.Height, Imaging.PixelFormat.Format32bppArgb)
    7. Using g = Graphics.FromImage(bmp)
    8. g.DrawImage(bmpIndexed, 0, 0)
    9. End Using
    10. NumericUpDown1.Value = NumericUpDown1.Value + 30
    11. bmaps.Images.Add(mole, bmp)
    12. End If
    13. Next
    14. Next
    15. PictureBox1.Invalidate()


    und

    VB.NET-Quellcode

    1. Cartographer.Add("bla.png")
    2. Cartographer.Add("blub.png")
    3. '....................
    4. paintbyname()



    und

    VB.NET-Quellcode

    1. Dim x As Integer = 0
    2. Dim ypsilon As Integer = 30
    3. For i = 0 To bmaps.Images.Count - 1
    4. x = ypsilon
    5. e.Graphics.DrawImage(bmaps.Images(i), New Rectangle(x, 0, 60, 80))
    6. ypsilon = ypsilon + 66
    7. Next
    @Schmandal Poste mal ein paar Originalbildchen.
    Wahrscheinlich müssen die geeignet gerendert werden, da musst Du Dir mal die Überladungen von DrawImage() ansehen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!