Picturebox Array erstellen

  • VB.NET

Es gibt 24 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Picturebox Array erstellen

    Hallo,
    ich würde gerne ein Array aus kleine Picture Boxen erstellen in denen ich jeweils ein Bild einfügen kann.
    Ich habe eine Variable X und eine Variable Y die ich aus einen Textfile einlese, diese Anzahl an Boxen soll dann erstellt werden.
    Größe sollte 20x20 Pixel sein, die X und Y Position möchte ich definieren können und welches Bild angezeigt wird.
    Der Name der jeweiligen Box sollte den X und Y Wert der Position enthalten. also z.B. "B1_1" für die erste Box.

    Hab da jetzt schon einiges versucht, komme aber auf keine Lösung, vielleicht kann mir wer Helfen.

    Danke und MfG
    Öhm. Und woran scheitert es?

    VB.NET-Quellcode

    1. Dim PicBoxArray(x, y) As PictureBox
    Danach in einer Doppelschleife die einzelnen PicBoxArray-Einträge durchgehen und ne New PictureBox mit den gewünschten Einstellungen festlegen (Größe, Position, Name). Wobei das mit dem Namen m.E. in ne falsche Richtung geht. Namen sind Schall und Rauch und sollten keine Informationen enthalten, die man für den Programmfluss hernimmt. Klar, ein sauberer Controlname ist immer gut (was bei B1_1 relativ ist). Aber bitte nicht aufgrund des Namens B5_8 irgendwelche Codeteile ausführen/überspringen.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Die PictureBoxen erstellst du am besten im Designer. Im Code ist das viel zu viel Arbeit und ist unübersichtlich. Im Designer kannst du dann auch die PictureBoxen benennen, wie du willst.

    Mach dir eine Prozedur
    Private Sub show_all_images(), die sich nur um das Suchen der ersten PictureBox, die frei ist, und um's Befüllen kümmert.

    Zuerst wird in dieser Prozedur alles geleert. Das gibt RAM frei.


    VB.NET-Quellcode

    1. 'alle PictureBoxen leeren.
    2. For Each PiB As PictureBox In Me.Controls.OfType(Of PictureBox)
    3. If PiB.Image IsNot Nothing Then PiB.Image = Nothing
    4. Next


    Dann eine Schleife über alle PictureBoxen, die du hast.
    Zuerst wird die erste befüllt, dann die zweite (denn in der ersten ist ja schon ein Bild dann drin), und so weiter.
    Lass dich von meinem Posting.Bilder nicht verunsichern, ich habe jetzt einfach Code aus einem Projekt kopiert. Das ist eine List(of Bitmap).

    VB.NET-Quellcode

    1. For Each [Bitmap] As Bitmap In Posting.Bilder
    2. ' Dies muss mit einem ‚Array of PictureBox‘ gemacht werden, weil „Controls.OfType(Of PictureBox)“ falschherum auflistet.
    3. For Each PB As PictureBox In {PictureBox1, PictureBox2, PictureBox3, PictureBox4, PictureBox5, PictureBox6, PictureBox7, PictureBox8, PictureBox9}
    4. If PB.Image Is Nothing AndAlso Bitmap IsNot Nothing Then
    5. PB.Image = Bitmap
    6. PB.Update()
    7. Exit For
    8. End If
    9. Next
    10. Next


    Noch eine Sache: Bilder müssen disposed werden, wenn sie nicht mehr gebraucht werden. Ich weiß jetzt nicht, um wie viele Bilder es sich bei dir handelt, und wie groß diese sind (kB, mehrere MB). Wenn in diesen (sagen wir) 9 PictureBoxen immer andere Bilder zu sehen sein sollen – so wie ich in diesem Thread nur die Anhänge dieses Threads sehe und nicht alle des ganzen Forums – dann musst du dir eine Prozedur Private Sub Load_the_pictures_only_when_shown_and_free_up_memory_after_an_Image_is_not_needed() machen, die die Bilder verwirft (disposed), die aktuell nicht gebraucht werden, und die lädt, die aktuell gebraucht werden. Aber darüber reden wir, wenn's soweit ist.
    @winke Namen sind Schall und Rauch, letzten Endes greifst Du über die Indizes zu.
    Es scheint mir, dass Du Dein Problem mit einem TableLayoutPanel lösen könntest.
    Was genau willst Du ereichen?
    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!

    RodFromGermany schrieb:

    Was genau willst Du ereichen?

    winke schrieb:

    Wie kann man das machen?
    In dieser Reihenfolge.
    Du kommst hier mit winzigen Häppchen. Offenbare zunächst den ganzen Plan.
    Das soll doch iein Spiel werden.
    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!
    Sorry, um es einfach zu erklären, ich habe ein Picturbox Array erstellt mit 10 x 10 Bildern.

    Habe dann die Größe (20x20Pixel) zugeordnet, die Positionen, und allen ein Bild zugeordnet.

    Nun brauch ich noch folgendes:
    Wenn ich auf eines dieser 100 Boxen klicke, soll das Bild gegen ein anderes ersetzt werden.


    So sieht das Ganze bis jetzt aus:
    PanelX und PanelY wird von einem Textfile eingelesen

    VB.NET-Quellcode

    1. Dim x As Integer
    2. Dim y As Integer
    3. Dim D(PanelX, PanelY) As PictureBox
    4. For x = 0 To PanelX
    5. For y = 0 To PanelY
    6. Dim pbox As New PictureBox
    7. pbox.Size = New Size(20, 20)
    8. pbox.Location = New Point(20 + 20 * x, 20 + 20 * y)
    9. pbox.Image = My.Resources.Bild1
    10. D(x, y) = pbox
    11. Controls.Add(pbox)
    12. Next
    13. Next
    14. End Sub
    Nee, was RfG lesen wollte, ist sowas:
    »Hallo. Ich will das Spiel Memory programmieren. Bisher habe ich x mal y PicBoxen, die als Bild die allgemeine Kartenrückseite haben und dieses anzeigen. Nun fehlt mir noch, wie ich jeder PicBox das eigentliche Bild zuweise, wie ich bei Klick auf eine PicBox das eigentliche Bild anzeige und wie ich dann vergleiche, ob ein zweites angeklicktes Bild identisch mit dem ersten ist, um dem Spieler einen Punkt zu geben und die PicBoxen aus dem Spiel zu entfernen. Desweiteren …«
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Hi

    Meine Gedanken dazu. Verwende kein PictureBox-Array sondern nur eine einzige PictureBox. Die Bilder zeichnest entsprechend an ihre Position (X,Y) in dieser einen PictureBox. Mit dem MouseMove-Event und ein wenig Mathematik weist Du genau über welchem Bild Du Dich mit der Maus befindest (PointInRect) und kannst auch entsprechend auf ein Mouse_Click or what ever reagieren. Stell Dir einfach diese eine PictureBox als Schachbrett vor das in Quadraten eingeteilt ist und Du jedes Quadrat per X und Y ansprechen bzw. X und Y ermitteln kannst.
    Mfg -Franky-
    Anstatt zu schreiben, was Du nicht machst, wäre es sinnvoll zu schreiben, was Du machen willst. Und das mit der Klickfunktion: Dafür gibt es das Schlüsselwort AddHandler, mit dem Du ein Event eines Controls mit einer Methode Deiner Wahl verknüpfen kannst.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Die Koordinaten stehen im Namen, der Name ist Teil des Controls und bei einer richtig erstellten EventHandler-Methode steckt das Control im ersten Parameter sender. Bleibt z.B. die Frage, wozu Du die Koordinaten brauchst. Aber all diese Informationen nur häppchenweise zu bekommen, um am Ende, nach vielleicht 40 Posts zu erkennen, wenn man das gesamte Ziel sieht, dass es von Anfang an anders hätte gemacht werden sollen, ist hier noch die Gefahr, von daher … auf wiedertschüss.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Ich brauche die Koordinaten damit dann weiß welches Bild geändert werden muss..

    Das Ganze brauch ich als Hilfsprogramm um eine Software für einen Mikrocontroller zu schreiben... aber ich weiß nicht warum das relevant ist, das ändert ja an meiner Frage nichts...
    …welches Bild geändert werden (also Image-Property einer PicBox; dann ist aber unklar, was die möglichen Werte sind bzw. welche Bilder zur Verfügung stehen) muss oder welche PicBox? Weil: die PicBox ist im sender, die Koordinaten im sender-Control-Name. Wenn sich die Koordinaten nicht ändert, wären die Koordinaten in der Tag-Property der PicBox besser aufgehoben, aber wenn Du es im Namen haben willst, dann mach es so. An welchem Codepunkt kommst Du nicht weiter? Wie sieht der Code um die AddHandler-Zeile herum aus, inkl. jener Zeile? Wie hast Du den EventHandler definiert, den Du in der AddHandler-Zeile mit angibst?
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Es ist relevant.
    Das ist ein klassisches Problem der Kommunikations-Theorie:
    Ein Frager beschreibt meist nicht das Problem, sondern hat eine Lösung im Kopf, die oft nicht oder nur schlecht funktioniert, und will nu unbedingt seine Lösung funktionsfähig gemacht bekommen.

    Angenommen ich muss nach München.
    Ich hab ein Fahrad.
    Da frag ich dann herum: "Wie kann ich mein Fahrad schneller machen?"
    Und das kann eine tagelange Diskussion werden, wie das geht, bis irgendwann rauskommt - ich muss nach München.
    "Ja nimm doch den Zug" - wäre die Antwort gewesen - eiglich zum schreien einfach.



    Wie dem auch sei.
    Eine sehr einfache Möglichkeit, viele Bilder anzuzeigen und draufzuklicksen (und da gibts dann auch ein Click-Event) gibts hier: ImageListView
    Aber ich sag dir gleich: Es ist kein Array von Pictureboxen.
    @VaporiZed

    Es funktioniert mal soweit, ich kann mit anklicken das Bild ändern.
    Da ich das ganze nur als Hilfstool für ein Mikrocontroller Programm brauche, muss ich noch in einem Array hinterlegen, welche Bilder ich geändert habe, deshalb brauche ich die Koordinaten.

    So finktioniert es bis jetzt:

    VB.NET-Quellcode

    1. Dim x As Integer
    2. Dim y As Integer
    3. For x = 0 To PanelX
    4. For y = 0 To PanelY
    5. Dim pbox As New PictureBox
    6. pbox.Size = New Size(20, 20)
    7. pbox.Location = New Point(20 + 20 * x, 20 + 20 * y)
    8. pbox.Image = My.Resources.Bild0
    9. AddHandler pbox.Click, AddressOf Dot_Click
    10. Controls.Add(pbox)
    11. DPanel(x, y) = pbox
    12. Next
    13. Next


    VB.NET-Quellcode

    1. Private Sub Dot_Click(dot As System.Object, e As System.EventArgs) Handles CLPanel.Click
    2. dot.Image = My.Resources.Bild2
    3. End Sub


    CodeTags korrigiert ~VaporiZed

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    winke schrieb:

    Ich brauche die Koordinaten damit dann weiß welches Bild geändert werden muss..
    Du brauchst das Bild, auf das geklickt wurde:

    VB.NET-Quellcode

    1. Private Sub PictureBox_Click(sender As Object, e As EventArgs) Handles PictureBox1.Click, PictureBox2.Click, PictureBox3.Click
    2. If sender.Equals(PictureBox1) Then
    3. PictureBox1.Image = My.Resources.Würfel
    4. ElseIf sender.Equals(PictureBox2) Then
    5. PictureBox2.Image = My.Resources.Würfel
    6. ElseIf sender.Equals(PictureBox3) Then
    7. PictureBox3.Image = My.Resources.Würfel
    8. End If
    9. End Sub
    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!
    Uiuiui, erster Schritt: Option Strict On. Denn ein Object hat kein Image. Daher muss erstmal ein DirectCast daher.
    Und dann eben vom in eine PictureBox umgewandelte dot den Namen auseinanderpfriemeln oder eben wie oben genannt über Tag an die Koordinaten kommen und fertig. Oder?

    RodFromGermany schrieb:

    Du brauchst das Bild, auf das geklickt wurde
    Jetzt Du auch noch mit dieser Formulierung. :S Für mich ist Bild hier ein Bitmap oder Image und somit der Image-Property-Wert der PicBox. Du beschreibst aber die angeklickte PicBox. Das ist ja bekanntlich ein Unterschied. Aber solange alle Beteiligten wissen, was gemeint ist …
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „VaporiZed“ ()

    @winke Falls Du Dich doch von der Idee mit einer PictureBox inspirieren lassen möchtest, hab ich da mal was schnell zusammen gebaut. Und weil das auf die schnelle war, darf das gern jeder verbessern. ;) So würde ich das ganze jedenfalls angehen und man kann so auf ein PictureBox-Array verzichten. Welches Bild dann an einer bestimmten Koordinate (X,Y) gezeichnet werden soll, steht ja in Fields(X,Y).Pos.X/Y Das ganze hat auch den Vorteil: Es ist flexibel falls sich mal die Anzahl oder die Größe der Felder ändert.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Option Strict On
    2. Option Explicit On
    3. Imports System.Runtime.InteropServices
    4. Public Class Form1
    5. Private Const FieldX As Integer = 15
    6. Private Const FieldY As Integer = 5
    7. Private Const FieldWidth As Integer = 20
    8. Private Const FieldHeight As Integer = 20
    9. Private Structure Field
    10. Dim Pos As Rectangle
    11. Dim State As Boolean
    12. ' was auch immer hier noch so rein soll
    13. ' zb Bilder oder oder oder
    14. End Structure
    15. Private ReadOnly Fields As Field(,) = New Field(FieldX - 1, FieldY - 1) {}
    16. <DllImport("User32.dll", EntryPoint:="PtInRect")>
    17. Private Shared Function PtInRect(<[In]> ByRef lprc As Rectangle,
    18. <[In]> pt As Point) As <MarshalAs(UnmanagedType.Bool)> Boolean
    19. End Function
    20. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    21. For intY As Integer = 0 To FieldY - 1
    22. For intX As Integer = 0 To FieldX - 1
    23. Fields(intX, intY).State = False
    24. Fields(intX, intY).Pos = New Rectangle(FieldWidth * intX,
    25. FieldHeight * intY,
    26. FieldWidth + (FieldWidth * intX),
    27. FieldHeight + (FieldHeight * intY))
    28. Next
    29. Next
    30. End Sub
    31. Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove
    32. Dim bolRectFound As Boolean = False
    33. For intY As Integer = 0 To FieldY - 1
    34. For intX As Integer = 0 To FieldX - 1
    35. If PtInRect(Fields(intX, intY).Pos, e.Location) Then
    36. bolRectFound = True
    37. Debug.Print("You are in the field (X,Y) = (" & intX.ToString & "," & intY.ToString & ")")
    38. End If
    39. If bolRectFound Then Exit For
    40. Next
    41. If bolRectFound Then Exit For
    42. Next
    43. End Sub
    44. Private Sub PictureBox1_MouseUp(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseUp
    45. Dim bolRectFound As Boolean = False
    46. For intY As Integer = 0 To FieldY - 1
    47. For intX As Integer = 0 To FieldX - 1
    48. If PtInRect(Fields(intX, intY).Pos, e.Location) Then
    49. bolRectFound = True
    50. Debug.Print("You clicked in the field (X,Y) = (" & intX.ToString & "," & intY.ToString & ")")
    51. Debug.Print("Current state is = " & Fields(intX, intY).State.ToString)
    52. Fields(intX, intY).State = Not Fields(intX, intY).State
    53. Debug.Print("Current state is now = " & Fields(intX, intY).State.ToString)
    54. End If
    55. If bolRectFound Then Exit For
    56. Next
    57. If bolRectFound Then Exit For
    58. Next
    59. End Sub
    60. Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
    61. For intX As Integer = 0 To FieldX
    62. e.Graphics.DrawLine(New Pen(Color.Black), FieldWidth * intX, 0,
    63. FieldWidth * intX, FieldHeight * FieldY)
    64. Next
    65. For intY As Integer = 0 To FieldY
    66. e.Graphics.DrawLine(New Pen(Color.Black), 0, FieldHeight * intY,
    67. FieldWidth * FieldX, FieldHeight * intY)
    68. Next
    69. End Sub
    70. End Class

    Mfg -Franky-

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „-Franky-“ ()