Pictureboxen zur Laufzeit dynamisch erstellen und erweitern

  • VB.NET

Es gibt 16 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Pictureboxen zur Laufzeit dynamisch erstellen und erweitern

    Hallo,

    ich benötige ein paar Denkanstöße für folgendes Vorhaben:

    Eine Applikation ermittelt per FileSystemWatcher, ob neue (Bild-)Dateien in einem Ordner eintreffen. Wenn ja, soll von diesem ein Thumbnail erstellt und dynamisch in kleinen Pictureboxen auf der Form angezeigt werden. Auf der Form muss jedes Thumbnail klickbar sein, so dass ich per Klick auf das Thumbnail für das Original eine Aktion auslösen kann, z.B. die Orginal-Datei wieder löschen oder ähnliches.

    Was bisher funktioniert ist der File-Watcher und das erstellen von Thumbnails. Was nicht funktioniert ist erstens, das dynamische erstellen, wenn es einfach aus einer eigenen Sub heraus gemacht wird (dann wird nichts angezeigt, im Gegensatz zu z.B. Timer- oder Button-Klick, da wird es angezeigt, ist aber unpraktisch, weil es ja automatisch passieren soll) und daraus folgend das Problem, dass immer nur das letzte Thumbnail klickbar ist.

    Ich hoffe irgendwer hat die zündenden Ideen.

    Besten Dank schon mal!!!

    Hier der bisherige Code

    Quellcode

    1. ​Option Explicit On
    2. Imports System
    3. Imports System.IO
    4. Imports Microsoft.VisualBasic
    5. Imports System.Security.Permissions
    6. Public Class Form1
    7. Public posY As Integer = 50
    8. Public posX As Integer = 50
    9. Dim i As Integer = 1
    10. Dim sDestination As String = "d:\Income\Original"
    11. Public Shared iAllPicsCounter As Integer 'Variable für anzahl der Bilder
    12. Public Shared allpics() As String 'Variable mit allen Bilddateinamen
    13. Public Shared pics() As PictureBox
    14. Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    15. 'Hauptformular maximieren, Contols "Schließen, minimieren ctc." ausblenden und farbe festlegen (FULLSCREEN) sowie Ecken abrunden
    16. Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
    17. Me.WindowState = FormWindowState.Maximized
    18. eckenabrunden(Me, 0, 0, Me.Width, Me.Height, 20)
    19. Me.BackColor = Color.WhiteSmoke
    20. myFilewatcher()
    21. End Sub
    22. Private Sub pics_Click(ByVal sender As Object, _
    23. ByVal e As System.EventArgs)
    24. ' Click-Ereignis des Button-Arrays auswerten
    25. Dim itemClicked As PictureBox = CType(sender, PictureBox)
    26. Dim index As Integer = -1I
    27. ' Das betroffene Element im Array suchen (allgemein);
    28. ' Möglich wäre etwa auch das Vorgehen über die eigens
    29. ' zugewiesene Name-Eigenschaft des Buttons.
    30. For i As Integer = LBound(pics) To UBound(pics)
    31. If pics(i) Is itemClicked Then
    32. index = i
    33. Exit For
    34. End If
    35. Next
    36. If index >= 0 Then ' Element im Array gefunden (sonst index = -1)
    37. ' Kurze Informations-MessageBox für das Codebeispiel
    38. MessageBox.Show("Sie haben den Button Nr. " & CStr(index) & " angeklickt", _
    39. "Index des Buttons ermittelt", _
    40. MessageBoxButtons.OK, _
    41. MessageBoxIcon.Information)
    42. End If
    43. End Sub
    44. Private Sub myFilewatcher()
    45. ' Create a new FileSystemWatcher and set its properties.
    46. Dim watcher As New FileSystemWatcher()
    47. watcher.Path = "D:\Income"
    48. ' Watch for changes in LastAccess and LastWrite times, and
    49. ' the renaming of files or directories.
    50. watcher.NotifyFilter = (NotifyFilters.LastAccess Or NotifyFilters.LastWrite Or NotifyFilters.FileName Or NotifyFilters.DirectoryName)
    51. ' Only watch text files.
    52. watcher.Filter = "*.jpg"
    53. ' Add event handlers.
    54. AddHandler watcher.Changed, AddressOf OnChanged
    55. AddHandler watcher.Created, AddressOf OnChanged
    56. AddHandler watcher.Deleted, AddressOf OnChanged
    57. 'AddHandler watcher.Renamed, AddressOf OnRenamed
    58. ' Begin watching.
    59. watcher.EnableRaisingEvents = True
    60. End Sub
    61. 'Define the event handlers.
    62. Private Shared Sub OnChanged(source As Object, e As FileSystemEventArgs)
    63. ' Specify what is done when a file is changed, created, or deleted.
    64. 'MsgBox("File: " & e.FullPath & " " & e.ChangeType)
    65. 'Wenn Datei reinkommt, dann verschieben in Income
    66. If e.ChangeType = 1 Then
    67. 'MsgBox(e.FullPath.ToString & " eingegangen")
    68. Form1.MoveFile(e.FullPath.ToString)
    69. End If
    70. End Sub
    71. Public Sub MoveFile(sQuelle As String)
    72. Dim sTime As String = Replace(TimeOfDay, ":", "")
    73. Dim sFileName As String = ""
    74. 'Dateinamen und Datei.Erweiterung aus Pfad extrhieren
    75. sFileName = IO.Path.GetFileName(sQuelle)
    76. 'Datei Verschieben in Income
    77. My.Computer.FileSystem.MoveFile(sQuelle, sDestination & "\" & sTime & "_" & sFileName)
    78. 'Counter hochzählen und Dateinamen in Array schreiben
    79. iAllPicsCounter = iAllPicsCounter + 1
    80. ReDim Preserve allpics(iAllPicsCounter)
    81. allpics(iAllPicsCounter) = sTime & "_" & sFileName
    82. AddPictures()
    83. End Sub
    84. Private Sub AddPictures()
    85. ReDim pics(iAllPicsCounter)
    86. pics(iAllPicsCounter) = New PictureBox
    87. With pics(iAllPicsCounter)
    88. .Image = Image.FromFile(sDestination & "\" & allpics(iAllPicsCounter)).GetThumbnailImage(100, 100, Nothing, Nothing)
    89. .Width = 100
    90. .Height = 100
    91. .Top = posY
    92. .Left = posX
    93. .Name = "Picbox" & CStr(iAllPicsCounter)
    94. .Parent = Me
    95. .BringToFront()
    96. .Visible = True
    97. End With
    98. eckenabrunden(pics(iAllPicsCounter), 0, 0, pics(iAllPicsCounter).Width, pics(iAllPicsCounter).Height, 20)
    99. Me.Controls.Add(pics(iAllPicsCounter))
    100. AddHandler pics(iAllPicsCounter).Click, AddressOf pics_Click
    101. If posX >= 800 Then
    102. posX = 50
    103. posY += 100
    104. Else
    105. posX += 110
    106. End If
    107. End Sub

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

    Ich hab mir jetzt Deinen Code nicht wirklich angesehen. Mein Vorschlag: Erstell Dir ein UserControl, zeichne darauf Dein ThumNail und steck dies in ein FlowLayoutPanel. Hier bleibt Dir schon mal das Rumgemache mit den Positionsangaben und den AddHandler-Anweisungen erspart. Mir scheint es so, als hättest Du Dir den Code Stück für Stück zusammenkopiert und nur wenig davon verstanden.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Erstmal besten Dank für deine Antwort, werde mir das FlowLayoutPanel mal anschauen.
    Denke ich verstehe den Code oben ganz gut, stoße eben nur auf das Problem, dass die Thumbs nicht angezeigt werden, zumindest dann nicht, wenn die über addPictures aufgerufen werden. Packt man das Bild für Bild über nen Button_Click_Event (manuelles klicken auf einen Button mit nahezu dem selben Code) erscheinen die Thumbs. Nur ist das nicht was ich will ;)
    eine Sache, die du machen solltest.. (ohne das ich auf den Rest eingehe)
    in Zeile 105 machst du : ReDim pics(iAllPicsCounter)
    damit löscht du alles vorher dagewesene und legst praktisch das Array neu mit der angegebenen Größe an.

    Wenn du die Daten, die VOR dem Redim im Array waren behalten willst, nimm: ReDim preserve pics(iAllPicsCounter), also das "preserve" nicht vergessen!
    Das ist völliger Blödsinn. Dieses alte Konstrukt sollte man gar nicht mehr verwenden. Es gibt typ. Listen und jede Menge andere Techniken. Der gezeigte Code hat an so vielen Stellen Schwächen, dass es absolut nicht lohnt, hier überhaupt noch anzusetzen.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    WOW.. du hast das Programmieren sicher mit der Muttermilch eingesogen :)
    Wie sollten mal nicht vergessen wo wir herkommen, und das auch Du sicher "am Anfang Karriere" nicht alles 1a gemacht hast.
    Erstmal gilt es ein Problem (das angesprochene) zu lösen. das man es anders machen kann, ist ne andere Geschichte.
    Das Zauberwort heißt Erfahrung.. und die kommt mit der Zeit.
    Und dieser Befehl hat durchaus seine Berechtigung.

    RoulettePilot schrieb:

    Und dieser Befehl hat durchaus seine Berechtigung.


    Dann lass mal sehen, wo genau dieses Konstrukt Deiner geschätzten Meinung nach heute noch angebracht ist.

    RoulettePilot schrieb:

    Wie sollten mal nicht vergessen wo wir herkommen, und das auch Du sicher "am Anfang Karriere" nicht alles 1a gemacht.


    Dann solltest Du lieber den Leuten beibringen, den Recher direkt mit ByteCode zu füttern. Entweder man vermittelt hier aktuelle Technik oder man lässt es bleiben.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Also,

    dass die Techniken mit Sicherheit nicht alle State of the art sind, dass man vieles, oder wegen mir auch alles, besser machen kann weiß ich auch. Das Problem bleibt dennoch bestehen. Wenn also einer der erfahrenen Programmieren eine Hilfestellung bieten kann, wäre das super. Im Grunde geht es um nichts weiter außer:
    1. Ordner überwachen ob JPG-Datei darin erstellt wird
    2. wenn dies der Fall ist, Thumbnail erstellen und
    3. das Thumbnail in einr 100x100 Picturebox anzeigen, die zur Laufzeit erstellt wird, weil ja auch immer welche dazu kommen können.
    4. muss jedes Thumbnail z.b. beim Anklicken den ursprünglichen Dateinamen in z.B. ner Messagbox ausgeben.

    Sachdienliche Hinweise sind durchaus willkommen.
    naja, wenn du Mekkerst vermittelst du nicht:
    Anstatt, wenn es Deiner Meinung nach "Blödsinn" ist sag doch, das er anstatt Dim Pics() z.B. lieber dim Pics as new List (of picurebox) nehmen soll, und er da wunderbar ADD und all das feine Zeugs machen kann.
    Da hilft du ihm mehr.

    Edit:
    Dann solltest Du lieber den Leuten beibringen, den Recher direkt mit ByteCode zu füttern. Entweder man vermittelt hier aktuelle Technik oder man lässt es bleiben.

    Ich bin nicht hier um Wissen zu vermitteln. Dafür gibs Schulen. Ich versuche an den Stellen wo es aktuell brennt nen Ansatz zu bieten.

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

    Wenn Du Deine Augen mal auf Post#3 in diesem Thread richtest, dann wirst Du feststellen, dass ich ohne Rummeckern einen Vorschlag zur Lösung gegeben habe. Dieser Vorschlag, liest man ein bisschen zwischen den Zeilen, sagt dem TE, dass er sein Konstrukt überdenken soll und das Ganze nochmal von neu aufrollen soll.

    Und, weil ich so ein netter Mensch bin, hab ich durchaus bereits eine funktionierende Lösung ausgearbeitet, die nur darauf wartet, bis der TE seine Meinung ändert, dann bin ich auch gerne bereit, diese mit ihm zu teilen, um ihm etwas besseres zu zeigen.

    Ich bin nur nicht gewillt, mich durch den Fetzen Code zu arbeiten, der nur vor Fehlern und altem Zeugs wimmelt. Aber: Bitte, wenn Du meinst, so ein guter Lehrer zu sein, dann mach Du ruhig weiter und schau, wie weit Du kommst. Good luck^^
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Welche Meinung soll ich ändern, ich wäre für jede Hilfe absolut dankbar, vor allem, wenn Sie ebenfalls dazu beiträgt meinen Programmierstil zu verbessern. Ich hatte nichts zu meckern und selber auch eingesehen, dass da sicherlich nicht viel das wirklich gelbe vom Ei ist. Mein Problem besteht eher darin, dass ich auch eine Lösung bräuchte. Wenn du also schon etwas hast was mir helfen würde, dann vielen Dank!
    Das Projekt findest Du im Anhang. Um zu testen, musst Du im Desginer der Form1-Klasse den Pfad, auf den der FileSystemWatcher zeigt, abändern. Einen Schönheitsfehler hat die FileSystemWatcher-Klasse jedoch. Wird im Ordner eine Datei erstellt, so wird, allem Anschein nach, das Created-Event geworfen, auch wenn das Betriebssystem mit dem Kopieren noch nicht fertig ist, respektive noch einen Filelock auf der Datei hat. Den Workaround (Try-Catch) siehst Du dann im Code. Ist nicht schön, gefällt mir selbst nicht, aber auf die Schnelle konnte ich leider keine bessere Lösung dafür finden, falls es überhaupt eine gibt.

    Bei Fragen, immer gerne.
    Dateien
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o

    SpaceyX schrieb:

    Mein Vorschlag: Erstell Dir ein UserControl
    UserControl ist hier völlig oversized. Es reicht, eine Klasse zu erstellen die von Control erbt.
    Man kann dein Projekt sogar entsprechend umbauen:

    VB.NET-Quellcode

    1. Public Class ThumbNail : Inherits Control
    und dann die DesignerDatei und Resourcen-Datei löschen.
    Die Klasse UserControl ist für was anneres konzipiert.

    Aber noch bessere Architektur wäre gar kein eigenes Control zu nehmen, denn son Thumbnail anzeigen kann jedes Control (via BackgroundImage).
    Und das Selbst-Reagieren des Controls auf MouseClicks ist total unflexibel, denn natürlich soll erst im Form auf die Klicks reagiert werden.