Linie in PictureBox

Hallo zusammen!

Ich habe ein Textfeld, in dem ich einen Wert eingebe. Wenn ich diesen ändere, soll mir in der PictureBox eine linie angezeigt werden. Die PictureBox wird durch einen Timer jede Sekunde aktualisiert, so dass mir praktisch von jeder Sekunde der Wert, auch wenn er gleich bleibt, in der PictureBox angezeigt werden soll und diese Werte dann durch Linien verbunden werden. Jede Sekunde ist also ein Wert auf der X-achse und der Wert im Textfeld für die Y-achse.
Kann mir da jemand helfen?

Danke, Axel

Hallo,

Ich habe ein Textfeld, in dem ich einen Wert eingebe. Wenn ich
diesen ändere, soll mir in der PictureBox eine linie angezeigt
werden. Die PictureBox wird durch einen Timer jede Sekunde
aktualisiert, so dass mir praktisch von jeder Sekunde der
Wert, auch wenn er gleich bleibt, in der PictureBox angezeigt
werden soll und diese Werte dann durch Linien verbunden
werden. Jede Sekunde ist also ein Wert auf der X-achse und der
Wert im Textfeld für die Y-achse.

Du meinst so etwas wie die grafische Anzeige der Prozessorauslastung im Taskmanager? Das würde ich so lösen:

  • Ein Array erstellen, das so viele Felder hat, wie Du ‚Spalten‘ (x) haben möchtest.
  • wenn neue Daten kommen, den Inhalt des Arrays verschieben (API-MoveMemory) und in das frei gewordenen Feld den neuen Wert eintragen.
  • Das Array grafisch darstellen, das sollte mit ‚.Line()-()‘ kein Problem sein. Wenn Du Autoredraw auf False stellst, stört es auch nicht, daß Du die Picbox dabei jedes mal löschen mußt, es flimmert nicht.

Reicht das, oder brauchst Du Code?

Gruß, Rainer

Ich glaube ich bräuchte Code! Bin noch nicht so der hellste in VB und weiß gar nicht so wirklich was du meinst.

Danke, Axel

Hallo Axel,

kein Problem, sieh Dir das mal an. Nur eine Picbox und einen Timer auf die Form legen, Code einfügen starten. Anpassen wird dann einfach werden.

Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)

Dim Daten() As Integer

Private Sub Form\_Load()
 Picture1.ScaleMode = 3 'Pixel
 Picture1.BackColor = QBColor(15)
 Picture1.AutoRedraw = True
 Form1.Show
 DoEvents
 ReDim Daten(Picture1.ScaleWidth)
 Daten(10) = 8
End Sub

Private Sub Timer1\_Timer()
 Dim i As Integer
 CopyMemory Daten(1), Daten(0), (UBound(Daten) - 1) \* 2 'Ein Feld ist bei Integer 2 Bytes lang
 Daten(0) = Int(Rnd(1) \* Picture1.ScaleHeight)
 Picture1.Cls
 For i = LBound(Daten) To UBound(Daten) - 1
 Picture1.Line (i, Daten(i))-(i + 1, Daten(i + 1)), 0
 Next
End Sub

OK?

Gruß, Rainer

Hallo Rainer,
habs in einem neuen Projekt ausprobiert und es geht hervorragend! Leider aber nicht in meinem Projekt. Der Code ist für mich schon viel zu kompliziert, so dass ich die Grätsche zum Ändern meines Projektes bekomme. Ich muss da ja irgendwie mein EA-feld haben und meinen Button, mit dem ich dann die Änderung bestätige. Ich weß aber nicht wie! Ich möchte ja das die Linie auf den Wert springt (z.B. 200), den ich im EA-Feld eingebe und mit dem Button bestätige.

Danke auf jeden Fall schon mal, Axel

Hallo Axel,

habs in einem neuen Projekt ausprobiert und es geht
hervorragend!

Gut.

Leider aber nicht in meinem Projekt.

Weniger gut. :smile: Das passen wir auch noch an. Das Prinzip ist aber schon mal richtig?

Der Code
ist für mich schon viel zu kompliziert, so dass ich die
Grätsche zum Ändern meines Projektes bekomme.

Ach was, so kompliziert ist es gar nicht.

Ich muss da ja
irgendwie mein EA-feld haben und meinen Button, mit dem ich
dann die Änderung bestätige. Ich weß aber nicht wie!

Da ist doch die Zeile … Daten(0) = XXXX … Da schreibst Du jeweils neue Daten in das Array.

Ich
möchte ja das die Linie auf den Wert springt (z.B. 200), den
ich im EA-Feld eingebe und mit dem Button bestätige.

OK. Das Programm macht folgendes.

In einem Array werden die letzen X Daten gespeichert, die eingegeben wurden. (Wie vile ist in dem Beispiel von der Größe der Picbox abhängig, steht in … Redim(Daten()) … ) In Diesem Array werden alle Werte um eine Stelle nach oben verschoben. In Daten(11) Steht dann, was vorher in Daten(10) stand. Das ginge auch mit einer Schleife, aber so geht es schnell. :smile:
Dann wird als erster Wert der neue Wert eingetragen, das Bild gelösch und das gesamte Array in der Picturebox grafisch angezeigt.

Was Du brauchst ist eigentlich nur die Zeile:

CopyMemory Daten(1), Daten(0), (UBound(Daten) - 1) * 2

In der Du statt Daten() den Namen Deines Arrays einträgst, in dem Du die Daten sammeln willst. Dann trägst Du in Dein Array bei (0) den neuen Wert ein und gibst das gesamte Array in der Picturebox aus.

Damit CopyMemory funktionieren kann, mußt Du die Zeile:

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)

in Deiner Deklaration stehen haben, das ist schon alles.

 Picture1.Cls
 For i = LBound(Daten) To UBound(Daten) - 1
 Picture1.Line (i, Daten(i))-(i + 1, Daten(i + 1)), 0
 Next

Lbound(Array) dürfte Null sein, UBound(Array) gibt die die Größe des Arrays zurück. Wenn Du das nicht flexibel gestalten willst, kannst Du da auch feste Werte verwenden.

Was ist noch unklar?

Gruß, Rainer

Hi Axel,

ich habe das Programm mal überarbeitet und kommentiert.
Kommst Du jetzt besser damit zurecht?

Option Explicit
'Option Explicit erzwingt die Deklaration von Variablen,
'das vermeidet Tippfehler, kannst Du auch weg lassen.
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
'hier wurde der API-Aufruf deklariert, nur so funktioniert er.
Dim Daten() As Integer
'Hier wurde das Array dimensioniert, die Größe aber noch nicht festgelegt,
'die kenne ich noch nicht, die richtet sich in dem Programm nach
'der Größe der Picturebox. Wenn Du sie kennst, kannst Du sie hier eintragen
'und Dir damit das Redim() ersparen.

Private Sub Form\_Load()
 Picture1.ScaleMode = 3 'Pixel
 Picture1.BackColor = QBColor(15)
 Picture1.AutoRedraw = True
 'Nur Einstellungen für die Picturebox, das muß nicht im Code stehen
 Form1.Show
 DoEvents
 'Die Form schon mal anzeigen, dann habe ich die Größe der Picturebox.
 ReDim Daten(Picture1.ScaleWidth)
 'Die Größe des Arrays wird festgelegt. Wenn Du mit festen Werten arbeitest,
 'kannst Du die Zeile weg lassen.
 Timer1.Interval = 10
 Timer1.Enabled = True
 'Der Timer wird gestartet
End Sub

Private Sub Timer1\_Timer()
 Dim i As Integer
 CopyMemory Daten(1), Daten(0), (UBound(Daten) - 1) \* 2 'Ein Feld ist bei Integer 2 Bytes lang
 'die Daten im Array wurden verschoben.

 'Das Selbe wäre auch so gegangen:
 '\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
 'ReDim Daten(100)
 'For i = 99 To 0 Step -1
 ' Daten(i + 1) = Daten(i)
 'Next
 '\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
 'Nur ist CopyMemory sehr viel schneller

 Daten(0) = Int(Rnd(1) \* Picture1.ScaleHeight)
 'Hier wird ein Zufallswert in das Array an die Stelle(0),
 'als erster Wert eingetragen, Da kommen die anzuzeigenden
 'Daten hin, der Zufallswert war nur für die Demo, damit
 'man etwas arbeiten sieht.

 Picture1.Cls
 For i = LBound(Daten) To UBound(Daten) - 1
 Picture1.Line (i, Daten(i))-(i + 1, Daten(i + 1)), 0
 Next
 'Das Bild wurde gelöscht und neu aufgebaut.
End Sub

Gruß, Rainer

Hallo Rainer,
vielen Dank für deine Hilfe, das ist echt nett! Ich habe den Code soweit eingefügt, doch in der Zeile „CopyMemory Daten(1), Daten(0), (UBound(Daten) - 1) * 2“ sagt mir das Programm am Start „Index außerhalb des gültigen Bereichs“. Verstehe ich nicht!
Weitere Frage: Ich habe in diesem Code keinen Blassen, wo ich da mein EA-Feld, das txtSrung heißt, implementieren soll um meine Werteänderung einzugeben. Wo mach ich das?

Das steht ganz oben:

Option Explicit
Private Declare Sub CopyMemory Lib „kernel32“ Alias „RtlMoveMemory“ (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Dim Daten() As Integer

Das steht in meiner Prozedur:

Private Sub cmdTangente_Click()
Picture1.ScaleMode = 3 'Pixel
Picture1.BackColor = QBColor(15)
Picture1.AutoRedraw = True
frmReglerauswahl.Show
DoEvents
ReDim Daten(Picture1.ScaleWidth)
Timer2.Interval = 10
Timer2.Enabled = True
End Sub

Das ist für den Timer:

Private Sub Timer2_Timer()
Dim i As Integer
CopyMemory Daten(1), Daten(0), (UBound(Daten) - 1) * 2
End Sub

Gruß
Axel

Hallo Axel,

vielen Dank für deine Hilfe, das ist echt nett! Ich habe den
Code soweit eingefügt, doch in der Zeile „CopyMemory Daten(1),
Daten(0), (UBound(Daten) - 1) * 2“ sagt mir das Programm am
Start „Index außerhalb des gültigen Bereichs“. Verstehe ich
nicht!

Das Array ist nicht dimensioniert.

Weitere Frage: Ich habe in diesem Code keinen Blassen, wo ich
da mein EA-Feld, das txtSrung heißt, implementieren soll um
meine Werteänderung einzugeben. Wo mach ich das?

Das steht ganz oben:

Option Explicit
Private Declare Sub CopyMemory Lib „kernel32“ Alias
„RtlMoveMemory“ (pDst As Any, pSrc As Any, ByVal ByteLen As
Long)
Dim Daten() As Integer

Das steht in meiner Prozedur:

Private Sub cmdTangente_Click()
Picture1.ScaleMode = 3 'Pixel
Picture1.BackColor = QBColor(15)
Picture1.AutoRedraw = True
frmReglerauswahl.Show
DoEvents
ReDim Daten(Picture1.ScaleWidth)
Timer2.Interval = 10
Timer2.Enabled = True
End Sub

Das ist für den Timer:

Private Sub Timer2_Timer()
Dim i As Integer
CopyMemory Daten(1), Daten(0), (UBound(Daten) - 1) * 2
End Sub

‚fast‘ alles OK. Du hast Die Anzeige noch nicht eingebaut, und gibst Deine Daten noch nicht ein. Aber erst das Problem:

Du hast in den Eigneschaften des Timers bereits den Interval festgelegt und auf 10 Millisekunden gestellt. Außerdem steht der auf Enabled = true. Der Timer löst aus, bevor in Form-Load das Array dimensioniert ist. Stelle in den Eigenschaften vom Timer Enabled auf False, dann ist der Fehler weg.

Das nächste:

Das ist für den Timer:

Private Sub Timer2_Timer()
Dim i As Integer
CopyMemory Daten(1), Daten(0), (UBound(Daten) - 1) * 2

hier baust Du ein:

Daten(0) = Val(txtSrung.Text)

Und noch die Anzeige:

Picture1.Cls
For i = LBound(Daten) To UBound(Daten) - 1
Picture1.Line (i, Daten(i))-(i + 1, Daten(i + 1)), 0
Next

End Sub

Dann bekommst Du eine Linie, die läuft, die sich jedes mal verändert, wenn Du etwas anderes in das Textfeld eingibst.

Gruß, Rainer

Guten Morgen Rainer!
Ja, also irgendwie funktioniert das alles nicht. Weiß nicht, ob ich vielleicht zu doof dafür bin?!
Jetzt zeigt er mir das Gleiche in der Zeile „For i = LBound(Daten) To UBound(Daten) - 1“ an.

Oben:

Private Declare Sub CopyMemory Lib „kernel32“ Alias „RtlMoveMemory“ (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Dim Daten() As Integer

Prozedur:

Private Sub cmdTangente_Click()
Dim i As Integer
Picture1.ScaleMode = 3
Picture1.BackColor = QBColor(15)
Picture1.AutoRedraw = True
Picture1.Scale (0, 1000)-(300, 0)
Picture1.Cls
For i = LBound(Daten) To UBound(Daten) - 1
Picture1.Line (i, Daten(i))-(i + 1, Daten(i + 1)), 0
Next
DoEvents
Daten(10) = 8
Timer2.Interval = 10
Timer2.Enabled = False
End Sub

Timer:

Private Sub Timer2_Timer()
Dim i As Integer
CopyMemory Daten(1), Daten(0), (UBound(Daten) - 1) * 2
Daten(0) = Val(txtSrung1.Text)
End Sub

Was mach ich da denn falsch???

Gruß, Axel

Mion Axel,

Ja, also irgendwie funktioniert das alles nicht. Weiß nicht,
ob ich vielleicht zu doof dafür bin?!

nein, Dir fehlt einfach ein wenig erfahrung, die sammelst Du gerade. :smile:

Jetzt zeigt er mir das Gleiche in der Zeile „For i =
LBound(Daten) To UBound(Daten) - 1“ an.

Wieder: Array nicht dimensioniert. Du hast jetzt den Befehl Redim() ganz entfernt. In Deinem Code steht aber …

Picture1.Scale (0, 1000)-(300, 0)

Du hast also 1000 Spalten, dann weißt Du, daß Dein Feld 1000 Elemente haben muß. Schreib doch einfach …

Dim Daten(1000) As Integer

… dann kannst Du Dir das Redim() sparen.

Oben:

Private Declare Sub CopyMemory Lib „kernel32“ Alias
„RtlMoveMemory“ (pDst As Any, pSrc As Any, ByVal ByteLen As
Long)
Dim Daten() As Integer

Prozedur:

Private Sub cmdTangente_Click()
Dim i As Integer
Picture1.ScaleMode = 3
Picture1.BackColor = QBColor(15)
Picture1.AutoRedraw = True
Picture1.Scale (0, 1000)-(300, 0)
Picture1.Cls
For i = LBound(Daten) To UBound(Daten) - 1
Picture1.Line (i, Daten(i))-(i + 1, Daten(i + 1)), 0
Next
DoEvents
Daten(10) = 8
Timer2.Interval = 10
Timer2.Enabled = False
End Sub

Timer:

Private Sub Timer2_Timer()
Dim i As Integer
CopyMemory Daten(1), Daten(0), (UBound(Daten) - 1) * 2
Daten(0) = Val(txtSrung1.Text)
End Sub

Da fehlt noch etwas, nach dem Verschieben mußt Du das Array anzeigen der Teil …

Picture1.Cls
For i = LBound(Daten) To UBound(Daten) - 1
Picture1.Line (i, Daten(i))-(i + 1, Daten(i + 1)), 0
Next

… gehört in den Timer, nach der Zeile CopyMemory …

Gruß, Rainer

Hi Axel,

mir ist da noch etwas aufgefallen …

Daten(10) = 8

die Zeile stammt aus meinem ‚Experimentier-Zustand‘ des Programms und ist überflüssig. Ich hatte nur mal eine Zahl in ein Feld geschrieben um zu sehen, ob ich die Daten in die richtige Richtung verschiebe. :smile: Ganz ohne ‚Probieren‘ komme ich eben auich nicht aus.

Gruß, Rainer

Juhu, das Programm meckert nicht mehr!!! Mir wird aber trotzdem nischt in der PictureBox angezeigt. Das ist doch blöde!

Meinst du nicht, da fehlt irgendwie was wie Picture1.PSet (blabla) oder so?

Gruß, Axel

Hallo,

Juhu, das Programm meckert nicht mehr!!!

OK, das klappt also jetzt.

Mir wird aber
trotzdem nischt in der PictureBox angezeigt. Das ist doch
blöde!

Dann hast Du zu früh aufgehört zu lesen.

Meinst du nicht, da fehlt irgendwie was wie Picture1.PSet
(blabla) oder so?

Nein, dafür ja Line()-().

Die Stelle …

:stuck_out_tongue:rivate Sub Timer2_Timer()
:smiley:im i As Integer
:CopyMemory Daten(1), Daten(0), (UBound(Daten) - 1) * 2
:End Sub

muß heißen:

:stuck_out_tongue:rivate Sub Timer2_Timer()
:smiley:im i As Integer
:CopyMemory Daten(1), Daten(0), (UBound(Daten) - 1) * 2
:smiley:aten(0) = Val(txtSrung1.Text)
:stuck_out_tongue:icture1.Cls
:For i = LBound(Daten) To UBound(Daten) - 1
:stuck_out_tongue:icture1.Line (i, Daten(i))-(i + 1, Daten(i + 1)), 0
:Next
:End Sub

… hatte ich geschrieben, dann wird auch etwas angezeigt.

Gruß, Rainer

Hi Rainer! Ich hatte den letzten Teil des Codes so eingefügt wie du es beschrieben hast. Es geht aber nicht, ohne Flax! Ich kann dir das Projekt ja mailen wenn du willst.

Gruß
Axel

Hi Axel,

Ich kann dir das Projekt ja mailen wenn du willst.

gute Idee, das kann nur eine Kleinigkeit sein. Mail mal, das kommt dann gleich zurück.

Gru8ß, Rainer

So, ist geschickt.

Hi Axel,

So, ist geschickt.

ist angekommen … ich konnte es aber nicht entpacken. Die Dateinamen habe ich aber gesehen … .xls ??? Das ist doch nicht etwa VBA? Sag nicht, ich würde Excel baruchen um das öffnen zu können. Da habe ich nur die Version ‚97‘. :smile:
Wenn das wirklich VBA ist, dann poste doch besser den Code hier, so viel davon wie möglich.

Gruß, Rainer

Hallo Rainer, hab dir 'ne e-mail geschrieben.

Gruß, Axel