Indizierte Textboxen

  • VB.NET

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von Peter329.

    Indizierte Textboxen

    Hi,

    ich möchte eine Eingabe Matrix für SUDOKO erstellen. Das sind 9 Quadrate mit jeweils 9 Feldern, also insgesamt 81 Felder. (s. angehängte Grafik)

    Die Indizierung soll erfolgen nach Unterquadrat, Zeile, Spalte, d.h. a(i, j, k), wobei i, j, k von 1 - 9 laufen.

    Wie macht man das in VB 2010?

    Die angehängte Form ist eine VB6 Anwendung - da ging die Indizierung recht einfach, soweit ich mich erinnere. Wenn man ein Feld mit gleichem Namen dupliziert hat, wurde es nach Anfrage sofort in einen Vektor umgewandelt. In VB 2010 wird einfach ein forlaufend nummerierter Variablenname generiert. Irgendwie vermisse ich in den Eigenschaften die Möglichkeit zur Indizierung.

    LG
    Peter
    Bilder
    • Sudoku.jpg

      72,69 kB, 528×488, 152 mal angesehen
    Alle Textboxen befinden sich unter anderem in einem Array bzw. einer List(of Control) in der Form, dieses kannst du in einer Schleife durchlaufen und kommst so an die Controls dran.

    Aber ich würde mir das Soduku Feld erst beim starten generieren und die erstellten Textboxen eigenständig in eine List(Of Textbox) packen, da hast du dann auch gleich die richtige Zuordnung.

    Peter329 schrieb:

    Wie macht man das in VB 2010?
    Mach Dir zunächst ein 3x3-Edit-UserControl, davon brauchst Du dann 9 Stück in Deiner GUI.
    Besser wäre es, die dicken 3x3-Begrenzungsrahmen nicht durch Controls, sondern im Paint-Event darzustellen, denn sie durchbrechen die interne Sudoku-Logik.
    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!
    Ich hab jetzt mal anfangen, die Hinweise umzusetzen.

    Ich generiere eine Textbox dynamisch mit folgendem Coding:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    3. Dim a As New TextBox
    4. a.Location = New Point(100, 200)
    5. a.Width = 30
    6. a.TextAlign = HorizontalAlignment.Center
    7. 'a.Font.Size = 14
    8. Me.Controls.Add(a)
    9. End Sub
    10. End Class


    Dazu hab ich jetzt einige Fragen:

    1. Wie kriege ich denn da jetzt meine Dimension hinein?
    2. Wie setze ich die Font Size auf 14? Mein Coding klappt nicht weil die Eigenschaft a.Font.Size "read only" ist.
    @Peter329:: So was:

    VB.NET-Quellcode

    1. Private allTb(8, 8) As TextBox
    2. Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    3. For x = 0 To 8
    4. For y = 0 To 8
    5. Dim a As New TextBox
    6. a.Location = New Point(30 * x, 30 * y)
    7. a.Width = 30
    8. a.TextAlign = HorizontalAlignment.Center
    9. a.Font = New Font("Arial", 12)
    10. Me.Controls.Add(a)
    11. allTb(x, y) = a
    12. Next
    13. Next
    14. 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!
    Supi! Herzlichen Dank erst mal!

    Jetzt müsste ich noch wissen, wie ich

    1. Ereignisprozeduren schreibe, die etwa den Click auf AllTab(1, 3) abfangen. Muss ich da jetzt 81 Prozeduren schreiben .... oder kann man das mit einer Prozedur erledigen, die einem die Koordinaten anliefert?

    2. Wie zeichne ich mit Paint die benötigten Rahmen?
    @Peter329:: Etwa so. Beim Malen der Linien musst Du noch etwas probieren, damit die Koordinaten, die Farbe und die Stricghstärke stimmen.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private allTb(8, 8) As TextBox
    3. Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    4. For x = 0 To 8
    5. For y = 0 To 8
    6. Dim a As New TextBox
    7. a.Location = New Point(30 * x, 30 * y)
    8. a.Width = 30
    9. a.TextAlign = HorizontalAlignment.Center
    10. a.Font = New Font("Arial", 12)
    11. a.Tag = 10 * x + y
    12. AddHandler a.Click, AddressOf Tb_Click
    13. Me.Controls.Add(a)
    14. allTb(x, y) = a
    15. Next
    16. Next
    17. End Sub
    18. Private Sub Tb_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    19. Dim tb As TextBox = DirectCast(sender, TextBox)
    20. Dim val = CInt(tb.Tag)
    21. Dim x = val \ 10
    22. Dim y = val - 10 * x
    23. MessageBox.Show(String.Format("{0}, {1}", x, y))
    24. End Sub
    25. Private Sub Form1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
    26. Dim pen = New Pen(Brushes.Black, 3)
    27. e.Graphics.DrawLine(pen, 0, 0, 500, 500)
    28. End Sub
    29. 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!
    mhh ... darf ich noch mal nachfragen?

    Bei der Prozedur Tb_Click fehlt doch die "Handles" Angabe. So wie das dasteht passiert bei mir überhaupt nix, wenn ich eines der Text Boxes anklicke.

    Normalerweise würde ich ja bei einer Textbox einfach im Studio die Prozedur generieren lassen .... aber gerade das geht hier ja nicht!

    Die Sache mit Paint muss ich mir noch mal genauer anschauen .... aber jetzt weiß ich ja, wo ich suchen muss.

    LG
    Peter
    Korrekt, das ist ersetzt durch dies, es gibt halt 2 Wege, die nach Rom führen:

    VB.NET-Quellcode

    1. AddHandler a.Click, AddressOf Tb_Click
    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!
    generierte Controls sind ziemlich grauselig, vor allem wenn nur die Location gesetzt ist, und keine weitere Layout-Logik.

    Imo günstiger wäre, du würdest dir 9 3*3-TableLayoutPanels nehmen, und die selbst wieder in ein 3*3-TableLayoutpanel verteilen, und dahinein deine Textboxen einordnen.

    Dann kannst du mit Docking weiterhin ein flexibles Layout gewährleisten - ich find Anwendungen, die man nicht resizen kann, immer ziemlich behindert.

    gugge auch Layout in WinForms

    Oder du machst das gleich alles im Designer, mittels Copy&Paste sollte das ja kein Act sein.

    für die Business-Logic von Sudoku musst du dir eh eine Abstraktions-Schicht schaffen, also listige Input-Klassen, von denen jede mit 3 9er-Gruppen weiterer Input-Klassen verknüpft ist.

    Vorzugweise Via Databinding sollte diese Abstraktionsschicht mit den Textboxen verknüpft sein.
    Ich hab den Hinweis mit dem Handler versucht umzusetzen. Die einzige Stelle, wo diese Anweisung hingehört, scheint mir in der Schleife im der Load Prozedur zu sein:

    VB.NET-Quellcode

    1. Private allTb(8, 8) As TextBox
    2. Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    3. For x = 0 To 8
    4. For y = 0 To 8
    5. Dim a As New TextBox
    6. AddHandler a.Click, AddressOf Tb_Click
    7. a.Location = New Point(30 * x, 30 * y)
    8. a.Width = 30
    9. a.TextAlign = HorizontalAlignment.Center
    10. a.Font = New Font("Arial", 12)
    11. Me.Controls.Add(a)
    12. allTb(x, y) = a
    13. Next
    14. Next
    15. End Sub
    16. Private Sub Tb_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    17. Dim tb As TextBox = DirectCast(sender, TextBox)
    18. Dim val = CInt(tb.Tag)
    19. Dim x = val \ 10
    20. Dim y = val - 10 * x
    21. MessageBox.Show(String.Format("{0}, {1}", x, y))
    22. End Sub


    Wenn ich das ausführe, kriege ich als Position immer (0, 0) ausgegeben. Was mache ich denn jetzt schon wieder falsch!

    Wenn ich das Debugge, dann enthält tb.Tag "Nothing" .... und demzufolge wird für x und y der Wert 0 errechnet.

    LG
    Peter

    P.S.:

    @EDR: natürlich sind deine Ideen super! Vielen Dank also! Aber irgendwie fühl ich mich da überfordert. Jetzt werd ich erst mal meine "hausbackene" Lösung verfolgen und mich danach mit den anspruchsvolleren Techniken auseinandersetzen.

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

    sonne75 schrieb:

    Ich glaube, du hast den Code im Post#7 übersehen, der im Expander ist.


    Hehehe, neee, das habe ich nicht übersehen. Das mit dem Handler ist wohl nachträglich eingefügt worden, nachdem ich den Code bereits mit Cut & Paste in mein Programm übernommen hatte.

    Aber JETZT verstehe ich auch wie das funktioniert! Und nun klappt das auch mit den Koordinaten!

    Ok, vielen Dank erst mal an alle Ratgeber. Nun kann ich versuchen den VB6 Code nach VB2010 zu übertragen.

    Und danach werde ich mich dann an die Ratschläge von @EDR machen ... ich will ja auch was lernen!

    LG
    Peter