Text Schreiben lassen

  • VB.NET

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

    das Thema gabs neulich schon. also die Lösung ist, dass man mit einem Timer bei jedem Tick immer einen Buchstaben anhängt. Textbox.AppendText.
    alles annere ohne Timer ist Murx, weil prozedural gedacht, wo eventbasiert programmiert werden muß.

    Achja - im anneren Thread hatte auch Picoflop mir zurecht wiedersprochen: mit dem neuen CTP-Async kann man sowas tatsächlich auch "scheinbar" prozedural implementieren.
    Kommt halt drauf an, was man haben will. Ich fand deinen Code auch ganz brauchbar, bis ich gemerkt habe, das andere Events erst abgearbeitet werden, wenn der mit dem Text durch ist. Da würde ich dann auch eher mit einem Timer vorlieb nehmen. Aber die Methode ist interessant, wieder was gelernt. ^^

    Kangaroo schrieb:

    ... und ich dachte das Zeitalter des Absolutismus wäre 1789 zu Ende gegangen :rolleyes:
    Auch nach Ende des Absolutismus gelten noch immer die Naturgesetze und die Gesetze der Logik. Folglich gibt es immer noch "funktioniert" und "funktioniert nicht", und richtig und falsch.
    Jedenfalls im technischen Bereich, und die Programmier-Wissenschaft ist ein solcher.

    Natürlich steht jedem frei, anders als eventorientiert vorzugehen - tatsächlich ist das der einzige Weg, meine Aussage "das ist Murx" annähernd zu verifizieren.
    Falsifizieren werdet ihr sie nicht können, oder ich wäre euch sehr dankbar, denn dann habt ihr meinen Horizont erweitert.
    Also bitte! Probiert einfach die bisher gegebenen Vorschläge auch mal aus, dann seht ihrs ja.

    Die einzig bisher mir bekannte Falsifikation ist die von Picoflop angeführte, und die setzt halt die Installation des CTP-Async-Frameworks voraus.
    Im April hab ich das noch so gemacht:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Dim MeinText As String
    3. Dim Zeichen As Integer
    4. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    5. MeinText = " Hier kommt die Maus... "
    6. Zeichen = 0
    7. Timer1.Interval = 250
    8. Timer1.Start()
    9. End Sub
    10. Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    11. TextBox1.Text &= MeinText.Substring(Zeichen, 1)
    12. Zeichen += 1
    13. If Zeichen = MeinText.Length - 1 Then
    14. TextBox1.Clear()
    15. Zeichen = 0
    16. End If
    17. End Sub
    18. End Class

    Das mir da was blockiert würde, sehe ich jetzt net.
    nana. also mindestens Kangaroo kennt sich glaub wirklich gut aus.

    Ich geh ihm blos immer auf die Nerven mit meine apodiktische Art, daherzureden. Aber wenn etwas Fakt ist, dann sagichauch, es ist Fakt.
    Ich denk mir die Fakts ja nicht aus, daher hinkt der Vergleich mittm Absolutismus. ;)

    Unwesen schrieb:

    Das mir da was blockiert würde, sehe ich jetzt net

    Forms.Timer arbeiten auf dem GUI-Thread: wenn also dort eine zeitintensive Verarbeitung stattfindet, wíird die Ausgabe "lagged".

    Insofern ist also der Vorschlag von ErfinderDesRades genauso ein 'Murx'-Kompromiss.

    ErfinderDesRades schrieb:

    Ich geh ihm blos immer auf die Nerven mit meine apodiktische Art, daherzureden.

    Stimmt, aber was wäre das Leben ohne Herausforderungen :)

    Nein, nun im Ernst: jeder möge die Lösung nehmen, die ihm unter Berücksichtigung der o.a. Punkte zusagt. Es gibt wirklich Pro und Contra ...
    Forms.Timer arbeiten auf dem GUI-Thread: wenn also dort eine zeitintensive Verarbeitung stattfindet, wíird die Ausgabe "lagged".
    Es geht darum, Text in einer Textbox anzuzeigen. Dassis doch nicht zeitintensiv.

    ich weiß jetzt auch nicht, welche vorschläge noch diskutiert werden. Diskutieren wir jetzt die Vorzüge verschiedener Timer? Dann bin ich ja auf jeden Fall zufrieden, das ist ja eventorientiert gedacht.

    Ansonsten scheints mir schnurz, ob der eine Timer um 5ms genauer geht als der annere. Das wird der User wohl kaum wahrnehmen können.
    also plädiere ich für den am einfachsten anzuwendenden: den Winforms-Timer.
    Na, das ist ja ein lustiger Thread ;)

    Fangen wir mal damit an, dass mein zuerst geposteter Code schlechte Programmierpraxis war, da er den GUI-Thread lahmlegte: -> no discussion, Asche auf mein Haupt.

    Das eigentliche Reizthema für mich ist dagegen dieser ganze dogmatische Dummfug , alles ohne Timer sei Murx da nicht eventbasierend (auf das Geschwurbel über Gesetze der Logik und Naturgesetze gehe ich lieber nicht ein).

    Auch in .NET gilt: was per se prozedural ist, darf auch prozedural programmiert werden und muss nicht dogmatisch in eine eventorientierte Zwangsjacke gesteckt werden. Und Timer lösen zwar Events aus, sind im Hintergrund jedoch nix anderes als Threads aus dem Threadpool die permanent im Kreis laufen um alle paar Millisekunden regelmässig 'Piep' zu sagen. Bis sie dann irgendwann von diesem schrecklichen Schicksal erlöst werden ...

    Jedenfalls ist das buchstabenweise Ausgeben eines Strings für mich von der Problemstellung her prozedural, darf also auchso gelöst werden, z.B. in einer Schleife die nach jeder Ausgabe eine Pause macht. Solange das in einem eigenem Thread geschieht, ist das absolut ok, immer noch prozedural, und auch nix anderes als der Timer eh macht.

    Themawechsel: warum jetzt keine Forms-Timer ? Diese Art optischen Firlefanz findet man z.B. oft in Splashscreens , die zu Anfang eines Programms Designfehler beim Laden des Programms überdecken oder (unerwünschte) Informationen über den Verfasser und sein unglückliches Programm geben sollen. Dort ist der arme GUI-Thread eh überlastet, so dass eine Lösung mit Forms-Timer danebengreift.

    Insofern besser gleich asyncron, wie: System.Timer / Thread / BeginInvoke ...
    Der extra Aufwand den unser Erfinder moniert ist eh minimal: ob ich nun Textbox1.Text &= char schreibe oder Textbox1.Invoke(Sub() txtBox.Text &= char) ist ja wohl ziemlich egal.


    Als Buße für meinen schlechten Code jetzt einen asynchronen:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Class FancyTextbox
    2. ' Buchstabenweise Ausgabe eines strings in der Textbox
    3. Public Shared Sub SlowText(ByVal txtBox As TextBox, ByVal text As String, ByVal updateInterval As Integer)
    4. Dim t As Thread = New Thread(Sub() updateTextBox(txtBox, text, 100)) With {.IsBackground = True, .Priority = ThreadPriority.Lowest}
    5. t.Start()
    6. End Sub
    7. ' update thread
    8. Private Shared Sub updateTextBox(ByVal tBox As TextBox, ByVal s As String, ByVal updateInterval As Integer)
    9. For Each c As Char In s
    10. Dim cl As Char = c ' good practice not to use iteration var in lambda expression
    11. tBox.Invoke(Sub() tBox.Text &= cl)
    12. Threading.Thread.Sleep(updateInterval)
    13. Next
    14. End Sub
    15. End Class


    ach, ich stell auchmal die eventbasierte Lösung vor:

    VB.NET-Quellcode

    1. Public Class Form2
    2. Private _ToWrite As Queue(Of Char)
    3. Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
    4. _ToWrite = New Queue(Of Char)("Hallo Welt")
    5. Timer1.Start()
    6. End Sub
    7. Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles Timer1.Tick
    8. TextBox1.AppendText(_ToWrite.Dequeue)
    9. If _ToWrite.Count = 0 Then Timer1.Stop()
    10. End Sub
    11. End Class