Hilfe bei Random Label Code

  • VB.NET

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von petaod.

    Hilfe bei Random Label Code

    Hallo,

    ich hatte hier schonmal die Frage gestellt, wie man einen Zufallstext aus einer Datei auf Labels übertragen kann. Das Beispielprojekt mit 4 Labels und 4 Spalten Text (1, 2, 3, 4 <- Stand in den Zeilen) hat soweit auch funktioniert. Jetzt soll das ganze aber mit 29 Labels funktionieren, tut es aber nicht...

    So sieht mein Code aus.
    Erst wird Farbe und Text geändert. Dann soll aus einen Button geklickt werden und der 29 Zeilen (1 Name pro Zeile) soll auf den Labels erscheinen.
    Könnt ihr mir helfen?

    VB.NET-Quellcode

    1. Public Class frmMain
    2. Private Sub btnSettxt_Click(sender As System.Object, e As System.EventArgs) Handles btnSettxt.Click
    3. Dim txtlns() As String = IO.File.ReadAllLines("a.txt", System.Text.Encoding.Default)
    4. Dim rnd As New Random
    5. Dim temp As Integer = 1
    6. Do
    7. Dim bnds As Integer = rnd.Next(0, txtlns.GetUpperBound(0) + 1)
    8. If Not TextExists(txtlns(bnds)) Then
    9. Me.Controls("lbl" & temp.ToString).Text = txtlns(bnds)
    10. temp += 1
    11. End If
    12. Loop Until (temp = 30)
    13. End Sub
    14. Function TextExists(ByVal txt As String) As Boolean
    15. For Each c As Control In Me.Controls
    16. If c.GetType().FullName = "System.Windows.Forms.Label" Then
    17. If c.Text = txt Then Return True
    18. End If
    19. Next
    20. Return False
    21. End Function
    22. Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    23. For i = 1 To 29
    24. Me.Controls("lbl" + i.ToString).Text = "Warte..."
    25. Me.Controls("lbl" + i.ToString).BackColor = Color.FromArgb(81, 81, 81)
    26. Next
    27. End Sub
    28. End Class


    Was ich noch vergessen habe: Er liest auch nicht alle Labels ein, mach also die Form_Load Schritte nicht bei allen Labels.
    Nein, 29, da bei 30 ja Schluss ist und er dann neu anfangen soll...

    Aber auch mit 30 geht es nicht, es werden nur vereinzelnd Labels eingelesen und es erscheint der gleiche Fehler:

    System.NullReferenceException

    Markiert ist dann das:

    Me.Controls("lbl" & temp.ToString).Text = txtlns(bnds)
    Das ist eine ziemlich ungünstige Methode.
    Sinnvoller wäre sowas hier:

    VB.NET-Quellcode

    1. Dim Labels As Label()
    2. Public Sub New()
    3. InitializeComponent()
    4. Labels = {lbl1, lbl2, ...}
    5. End Sub
    6. Sub Foo()
    7. For Each i In Labels
    8. i.Text = ...
    9. Next
    10. End Sub

    Aber auch das ist nicht optimal. Wofür werden denn die Labels verwendet. Schon klar, es wird Text aus einer Datei angezeigt. Aber was wird denn beispielsweise angezeigt. Vielleicht eignet sich ein anderes Control besser zum Anzeigen der Daten.

    PS: Zufällig ordnen tut man gerne so:

    VB.NET-Quellcode

    1. Dim Input As IEnumerable(Of ...)
    2. Dim Rnd As New Random
    3. Dim Output = From p In Input Order By Rnd.Next

    Dadurch ist auch gegeben, dass Elemente nicht zweimal ausgewählt werden.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Also angezeigt werden sollen Namen. Immer nur einer pro Label.
    Du meinst also (sofern ich das verstehe), dass es besser ist, die Labels einzeln im Code abzurufen, anstatt eine automatisch Generierte Nummer an "lbl" zu setzen?
    Ja.
    Also jein.
    Kommt drauf an. Es ist allgemein sinnvoll, Controls aussagekräftige Namen zu geben. In diesem Post wird ein Bild gezeigt, das zeigt, wie man es genau nicht machen soll ^^
    Wenn 29 Namen angezeigt werden sollen, könntest Du Dir vielleicht die ListBox anschauen. Die zeigt eine Liste von Einträgen an. Die kann man sogar super mit Datenbindung ausstatten.
    Kannst Du villeicht mal einen Screenshot der Form machen? Dann können wir und ein bisschen besser vorstellen, wie das Ganze aussieht.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Ach so. Ok. Soll das Programm später noch mehr anzeigen können? Dann würde sich nämlich anbieten, daraus ein UserControl zu basteln. Das UserControl hat seinerseits die Labels und bietet eine Methode, mit dem man die Texte setzen kann.
    z.B. Public Sub SetRandomNames(ByVal Names As IEnumerable(Of String))
    In der Methode prüfst Du, ob die passende Anzahl an Elementen vorhanden ist (um Folgefehler zu vermeiden), "verzufallisierst" Du die Namen und weist sie anschließend den Labels zu. Die Labels kannst Du dann wie im ersten Codeschnipsel in Post #8 in ein Array packen.
    Dadurch kannst Du die Texte problemlos zuweisen.
    Du Debuggst das Projekt einmal, dann hast Du in der ToolBox das UserControl. Zieh das auf die Form und schon hast Du eine übersichtliche Methode, die Texte anzuzeigen. In der Form schreibst Du dann nur noch DeinControl.SetRandomNames(System.IO.File.ReadAllLines(...)) in eine Sub, und schon hat sich's erledigt.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Irgendwie werde ich das Gefühl nicht los, dass man das Problem etwas objektorientierter angehen könnte.
    Eine Klasse Tisch mit Properties Position, Owner, Grafikobjekt... instantiiert und in einer List gehalten von einer Klasse Raum
    Dazu eine List (Of Person) deren Member von einer Zufallsmethode auf die Tische zugewiesen werden.

    Wenn das Ganze in einer komplexeren Umgebung verwendet werden soll, ist mir der bestehende Ansatz zu unflexibel.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --