Kästchenmatrix, Logo Generator

  • VB.NET

Es gibt 19 Antworten in diesem Thema. Der letzte Beitrag () ist von FreakJNS.

    Kästchenmatrix, Logo Generator

    Hallo, ich habe mal ne Frage zu folgender Idee: Ich möchte eine 16*16 Kästchen Matrix erstellen. Diese Kästchen sollte man durch Mausklick schwarzfüllen können und bei erneutem Klick wieder weiß. Nun sollen erstmal die erste Spalte betrachtet werden.

    Die 16 Spaltenkästchen representieren eine 16 Bit Zahl dementsprechnend muss jedes Kästchen mit einer Zahl versehen werden: von oben nach unten 1 2 4 8 16 32 64 128 256 512... 32768. Nun sollen bei Auswahl von einem oder mehreren Kästchen die Zahlen addiert werden. Genauso das gleiche soll für alle 16 Spalten passieren.

    Bei erneutem Klick auf ein Kästechen soll dieses Weiß gefüllt werden und die entsprechende Zahl von der Summe abgezogen werden.

    Beim ButtonKlick: File Speichern sollen die 16 Summen der Spalten in einem Textfile als Array abgespeichert werden. Das Textfile soll in etwa so aussehen.

    char array [16]=[1][256][8][29][512][255].......[50000]

    Das Ganze dient dazu 16*16 Pixel Logos für ein Display zu erstellen.
    @colombo010:: Willkommen im Fofrum. :thumbup:
    Du willst also eine 16 * 16-Binärmatrix erstellen.
    Fein.
    Wo ist das Problem?
    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!
    Hallo, Danke für die schnelle Antwort. Das Problem ist. Dass ich mit VB bisher nur ein zwei Zeilen Progrämmchen geschrieben habe. Somit keine Erfahrung damit habe und deshalb das Problem das Ganze umzusetzen bzw einen Ansatz zu finden.
    @colombo010:: Mach Dir ein 16*16-Boolean-Array.
    Nimm Dir eine PictureBox. Dort brauchst Du das Paint- und das MouseDown-Event.
    In Paint malst Du den aktuellen Zustand des Boolean-Arrays.
    In MouseDown ermittelst Du aus den Klick-Koordinaten die Indizes des Boolean-Arrays, änderst das Boolean-Array entsprechend und invalidisierst die PictureBox.
    Feddich.
    Nun ergreife die Initiative und bemühe die Suchfunktion im Forum und bei Frau Google.
    Zu jedem der Teilprobleme findest Du mehrere genau passende Lösungen - heißt: "Ich hab nix passendes gefunden" ist eine Ausrede :!:
    -----
    Zerlege Dein Projekt in disjunkte Teilprobleme, die Du in je einem separaten kleinen Testprogramm löst.
    Sind alle zu Deiner Zufriedenheit gelöst, mach ein neues Projekt, in dem Du alles zusammenfasst.
    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!
    Hmm...

    Als erstes würde ich daran gehen, eine Klasse für deine Matrizen zu bauen, mit der du dann arbeiten kannst. Nenn sie meinetwegen Matrix. Sie soll dazu dienen, 16x16 Binärwerte zu verwalten. Dafür bietet sich ein zweidimensionales Array aus Boolean-Werten an.

    VB.NET-Quellcode

    1. Class Matrix
    2. Private _matrix(15, 15) As Boolean
    3. End Class

    Sinnvoll sind dann Methoden, um einzelne Pixel (z.B. aus einem Mausevent deiner Anwendung heraus) lesen und setzen zu können. Also sowas wie

    VB.NET-Quellcode

    1. Public Sub SetPixel(Byval x As Integer, ByVal y As Integer, Byval value As Boolean)
    und

    VB.NET-Quellcode

    1. Public Function GetPixel(ByVal x As Integer, ByVal y As Integer) As Boolean

    Du möchtest den Inhalt später offensichtlich in Textform irgendwo ablegen, also implementierst du zusätzlich eine Funktion die dir die Daten deiner Matrix als String liefert. Auf den ersten Blick bietet sich dafür ein Überschreiben von ToString() an, da du aber mit hoher Wahrscheinlichkeit solche Strings auch wieder einlesen willst, brauchst du auch eine Methode, die einen String wieder in die interne Matrix umwandelt, von daher würde ich ToString() nicht nehmen und ein eigenes Funktionspaar dafür erfinden. Zum Beispiel

    VB.NET-Quellcode

    1. Public Function GetText() As String
    2. Public Sub FromText(ByVal value As String)

    Eine Alternative wäre auch, das als Eigenschaft (Property) zu realisieren:

    VB.NET-Quellcode

    1. Public Property Text As String
    2. Get
    3. '...
    4. End Get
    5. Set
    6. '...
    7. End Set
    8. End Property

    Deine Frage wird nun sein, wie kann man aus den 256 True/False-Werten die sechzehn 16-bit-Integer-Werte bauen.
    Das wäre z.B. eine Möglichkeit für den Get-Teil des Properties bzw. der GetText()-Funktion:

    VB.NET-Quellcode

    1. Dim result As New StringBuilder()
    2. For x As Integer = 0 To 15
    3. Dim wert As Integer = 0
    4. For y As Integer = 0 To 15
    5. If _matrix(x, y) Then
    6. wert += 2 ^ y
    7. End If
    8. Next y
    9. result.AppendFormat("[{0}]", wert)
    10. Next x
    11. Return result.ToString()

    Später wirst du diesen String wieder einlesen wollen, d.h. du musst eine Zeichenfolge wieder in ihre 16 Zahlenwerte zerlegen und diese interpretieren. Von daher würde ich deinen Ansatz, die Werte in [ und ] einzuschließen, vermutlich nicht wählen, sondern sie höchstens durch ein Komma (o.ä.) voneinander trennen. Das macht es hinterher einfacher:

    VB.NET-Quellcode

    1. If x > 0 Then
    2. result.Append(",")
    3. End If
    4. result.AppendFormat("{0}", wert)
    (statt der Zeile result.AppendFormat im vorherigen Abschnitt)
    Dann könnte das Einlesen (Property Set bzw. FromText()-Methode) so aussehen:

    VB.NET-Quellcode

    1. Dim werte() As String = value.Split(","c)
    2. For x As Integer = 0 To 15
    3. For y As Integer = 0 To 15
    4. _matrix(x, y) = (werte(x) And (2 ^ y)) <> 0
    5. Next y
    6. Next x

    Beachte, dass hier keinerlei Fehlerbehandlung enthalten ist, d.h. wenn jemand an deinen Dateien herummanipuliert, kann es beim Einlesen schnell zu Laufzeitfehlern kommen, die man berücksichtigen sollte.
    Wie du die Verbindung zwischen deiner Matrix-Klasse und dem eigentlich Zeichnen der Matrix herstellen kannst, dazu hat RodFromGermany ja schon ein paar Zeilen geschrieben.
    Weltherrschaft erlangen: 1%
    Ist dein Problem erledigt? -> Dann markiere das Thema bitte entsprechend.
    Waren Beiträge dieser Diskussion dabei hilfreich? -> Dann klick dort jeweils auf den Hilfreich-Button.
    Danke.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Arby“ () aus folgendem Grund: Property Get und Set vertauscht. :S ToString() vergessen

    Arby schrieb:

    deinen Ansatz, die Werte in [ und ] einzuschließen, vermutlich nicht wählen, sondern sie höchstens durch ein Komma (o.ä.) voneinander trennen. Das macht es hinterher einfacher:

    Joa, mehr oder weniger ^^

    Wenn du einfach den eingelesenen String nimmst, und dann alle "[" durch String.Empty und alle "]" durch ein Komma ersetzt, dann haben wir das doch ;)

    Bsp.:

    Eingelesener String: "[1][256][8][29][512][255]"
    str.Replace("[", String.Empty).Replace("]", ",")
    Result: "1,256,8,29,512,255"
    »There's no need to "teach" atheism. It's the natural result of education without indoctrination.« — Ricky Gervais

    ThePlexian schrieb:

    Result: "1,256,8,29,512,255"

    Nicht ganz.
    Bei deinem Ansatz käme "1,256,8,29,512,255," heraus. Aber so ginge es auch, man muss den 17. Teilstring, der dann beim Split() entsteht, ja nicht interpretieren.
    Weltherrschaft erlangen: 1%
    Ist dein Problem erledigt? -> Dann markiere das Thema bitte entsprechend.
    Waren Beiträge dieser Diskussion dabei hilfreich? -> Dann klick dort jeweils auf den Hilfreich-Button.
    Danke.
    hab mir schonmal 16*16 PictureBox gemalt und kann mit


    Quellcode

    1. Private Sub PictureBox1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox1.Click
    2. PictureBox1.BackColor = Color.Black



    Wie kann man denn bei erneutem Klick das Ganze weiß machen. Komme aus der C Welt und deshalb bin ich total überfordert damit. Google hat mir bisher wenig geholfen^^.

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

    eine Alternative wäre, ein DatagridView zu missbrauchen.
    guggemol, wassich in [VB 2010] LED-Matrix (Programmstruktur-Beschleunigen) angehängt hab.

    Ist aber eiglcih kein Anfänger -Stoff

    ah, hier noch was noch passenderes:
    Dateien
    • LedModel.zip

      (41,12 kB, 384 mal heruntergeladen, zuletzt: )

    nafets3646 schrieb:

    Wenn du deine Matrix wirklich in nem Int speichern willst, kannst du das über Bitshifting machen.
    Das ist mir auch klar was du meinst. Ich komme aus der reinen C Welt. Die Logik wie ich das machen muss ist nicht das Problem. Nur mir fehlt das Gefühl für die Objektorientierte Programmierung und deshalb haperts auch an der Umsetzung naja.
    Ich muss, dann wohl weiter nach ähnlichen einfachen Sachen suchen.
    Ich finde sowas vollkommen übertrieben für dieses kleine Problem. In .Net oder allgemein in OOP macht man sich normalerweise keine Gedanken darüber, möglichst wenig Speicher zu verbrauchen, man geht danach, was am einfachsten und intuitivsten umzusetzen ist. Ein 16*16-Boolean-Array braucht zwar 512 Bytes, ist dafür aber schön einfach zu verwalten, deine Bitshift-Lösung braucht nur 32 Byte, ist aber vergleichsweise kompliziert. Wir OOP-Programmierer sind halt faul (eigentlich nicht, wir müssen uns dafür über anderes Gedanken machen ;) ).

    colombo010 schrieb:

    hab mir schonmal 16*16 PictureBox gemalt
    Halte ich für oversized. Eine einzige reicht aus, Du musst nur wissen, wo Du hinklickst und wo Du hinmalst. Mach mal:

    VB.NET-Quellcode

    1. Private Sub PictureBox1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
    2. Label1.Text = CInt(e.X / PictureBox1.Width * 15).ToString
    3. Label2.Text = CInt(e.Y / PictureBox1.Height * 15).ToString
    4. End Sub
    Und schon hast Du für Maus-Aktionen aus den Mauskoordinaten in Deiner PictureBox die Spalten- und Zeilennummer Deines Arrays.
    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!
    @colombo010
    So wie ich Post #9 interpretiere hast du 16*16 Pictureboxen auf die Form 'gezogen'. Mach das nicht - eine einzige Picturebox oder ein einziges Panel reichen. Im Paint-Event des entsprechenden Controls kannst du zeichnen, siehe dazu mal in mein GDI+ Tutorial (siehe Signatur) rein.

    Ich würde hier zwei Klassen schreiben:
    1) KästchenMatrix: Matrix verwalten (also intern ein 2D Boolean-Array und dann die 'get- und setPixel'-Methoden bzw was sich noch so anbietet)
    2) KästchenMatrixControl: ein Control um die KästchenMatrix-Klasse darzustellen und zu steuern (=> GDI+ zum darstellen, Mausklicks zum steuern)

    Hinweis: Die KästchenMatrix muss intern nichtmal auf einem Boolean-Array basieren. Wenn zusätzliche Informationen (z.B. der Wert eines Pixels => 2,4,8,16,...) dazu kommen könnte es durchaus Hilfreich sein eine Kästchen-Klasse zu schreiben und die KästchenMatrix-Klasse eben auf einem Kästchen-Array basieren zu lassen. Im Konstruktor der Matrix-Klasse würde dann das Array angelegt werden und dafür gesorgt, dass alle Kästchen ihre passende Werte haben.

    Auszuwerten welches Kästchen geklickt wurde ist ja leicht - Das Control weiß wie breit/hoch ein Kästchen darzustellen ist. In den Mouse-Events bekommst du die Klick-Position.

    VB.NET-Quellcode

    1. dim PixelX as Integer = mouse.X \ KästchenBreite '\ => Integerdivision!

    Schon weißt du welches Pixel angeklickt wurde und kannst es an die Matrix-Klasse weiterleiten, z.B. meineMatrix.TogglePixel(PixelX,PixelY). Neuzeichnen löst man mit dasControl.Invalidate aus.
    @RodFromGermany ich glaube bei deiner Berechnung hat sich ein Fehlerchen eingeschlichen, böse C&P-Bremse^^ Außerdem rundet CInt(), darum würde ich Integer-Division nutzen. Alternativ müsstes du noch Math.Floor() dazwischenschalten.

    Nun ist es einfach auch den Zahlenwert in das entsprechende Kästchen zu zeichnen. Um den Wert einer Zeile zu bekommen musst brauchst du eine einfache Schleife die einfach die Kästchen-Elemente einer Zeile durchläuft und die Werte summiert.

    FreakJNS schrieb:

    hat sich ein Fehlerchen eingeschlichen
    Diesen hab ich sogar mal ausprobiert, er funktioniert wegen der Null-Basierung, denn es gilt immer:

    Quellcode

    1. e.X < PictureBox1.Width
    2. e.Y < PictureBox1.Height
    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 bei mir ist das Buggy^^
    z.B. X = 49
    bei dir kommt der Index 2 raus, bei mir Index 3 (welcher auch stimmen sollte).

    0-15 = 0
    16-30=1
    31-45=2
    46-60=3

    Edit: Moment, wenn die 15 bedeutet, dass auch wirklich 15 Kästchen Hoch/Breit dargestellt SIND, dann könnte es stimmen. Keine Zeit das nachzugucken, muss weg xD

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