Verwendung von PB mit KI - und Frage zu WindowEvent

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
stab
Beiträge: 99
Registriert: 24.02.2006 16:09
Computerausstattung: 286er Big Tower; 16MHz; 1MB Ram; 40MB Festplatte, 5 1/4" und 3 1/2" Diskettenlaufwerk; VGA Farbmonitor 14"; Windows 3.1; PureBasic 0.5
Wohnort: Hardt
Kontaktdaten:

Verwendung von PB mit KI - und Frage zu WindowEvent

Beitrag von stab »

Hallo PB Freunde,

ich wollte mal fragen, inwieweit Ihr ChatGPT oder andere KI beim Programmieren mit PB nutzt und ob Ihr evtl. dazu einige Tipps auf Lager habt. Ob es sich evtl. lohnt, ChatGPT Plus für Programmierarbeiten mit PB zu verwenden.

Ich selber gehöre ja dem älteren Semester an, wie Ihr an meiner Hardwareausstattung erkennen könnt. Habe ein paar PB-Projekte verwirklicht, die auch kommerziell von meinen Kunden genutzt werden. Programmieren ist für mich aber eher eine Nebenbeschäftigung, die mir dann allerdings auch Spaß macht. (Wenn niemend drängt)

Ich war heute Morgen super begeistert. Ich benötigte auf die Schnelle für mich ein simples Batch-Script, um per robocopy meine auf dem Netzlaufwerk befindlichen Dateien lokal abzugleichen.
Nichts löschen, sondern nur neuere Dateien kopieren und ggf. ältere mit gleichem Namen überschreiben. Wer robocopy kennt, kennt die Anzahl der Parameter.

Anstatt alle Parameter zu durchforsten, kam ich auf die Idee, mal ChatGPT zu fragen und erhielt sofort das funktionierende Script:

Code: Alles auswählen

robocopy "Z:\Quelle" "D:\Ziel" /E /XO
Dann kam ich auf die Idee zu fragen, ob und wie sich das in PB realisieren lässt.

Die Fragerunde ging dann immer weiter (willst du noch dies oder jenes), bis ich letztendlich erstmal zufrieden war und ein schönes kleines Programm erhalten habe.
ChatGPT vertat sich anfangs noch mit den Parametern der Funktionen ReadPreferenceString() und WritePreferenceString(). Hier wurden fälschlicherweise 3 statt 2 Parameter verlangt.
Das konnte ich aber wiederum mit Übermittlung meiner PB Version meinem Gegenüber mitteilen. Nach ein paar Sekunden Recherche wurde mir dann recht gegeben. ChatGPT hatte sich vertan und die Parameter der Funktion mit einer anderen Programmiersprache verwechselt. Nach durchforsten der PB-Dokumentation durch ChatGPT wurde dann auch dies berichtigt.

Hier die Code-Zeilen im Original, die mir übermittelt wurden. Der Start wäre allerdings verbesserungswürdig. Man hat den Eindruck, es passiert erstmal nichts.

Code: Alles auswählen

; #########################################################
; Backup Tool in PureBasic
; Autor: [Dein Name]
; Version: 1.3
; Datum:   04.10.2025
;
; Änderungen:
; - Quelle und Ziel per Dialog auswählbar
; - Zuletzt genutzte Pfade werden in BackupTool.ini gespeichert
; - Fortschrittsanzeige + Log im GUI
; - NEU: Log kann in eine Textdatei gespeichert werden
; #########################################################

EnableExplicit

Global totalFiles, copiedFiles, src.s, dst.s
Global iniFile.s = GetPathPart(ProgramFilename()) + "BackupTool.ini"

;---------------------------------
; INI-Funktionen (korrigiert)
;---------------------------------
Procedure LoadSettings()
  If OpenPreferences(iniFile)
    PreferenceGroup("Paths")
    src = ReadPreferenceString("Source", "")
    dst = ReadPreferenceString("Target", "")
    ClosePreferences()
  Else
    src = ""
    dst = ""
  EndIf
EndProcedure

Procedure SaveSettings()
  If CreatePreferences(iniFile)
    PreferenceGroup("Paths")
    WritePreferenceString("Source", src)
    WritePreferenceString("Target", dst)
    ClosePreferences()
  EndIf
EndProcedure

;---------------------------------
; Zählt alle Dateien im Quellordner (rekursiv)
;---------------------------------
Procedure.i CountFiles(src.s)
  Protected dir, entry.s, type, count.i = 0
  
  dir = ExamineDirectory(#PB_Any, src, "*.*")
  If dir
    While NextDirectoryEntry(dir)
      entry = DirectoryEntryName(dir)
      type  = DirectoryEntryType(dir)
      
      If type = #PB_DirectoryEntry_File
        count + 1
      ElseIf type = #PB_DirectoryEntry_Directory
        If entry <> "." And entry <> ".."
          count + CountFiles(src + "\" + entry)
        EndIf
      EndIf
    Wend
    FinishDirectory(dir)
  EndIf
  
  ProcedureReturn count
EndProcedure

;---------------------------------
; Kopiert neuere Dateien (rekursiv) + Fortschritt + Log
;---------------------------------
Procedure CopyNewerFiles(src.s, dst.s)
  Protected dir, entry.s, fileSrc.s, fileDst.s
  Protected type, dateSrc.q, dateDst.q, progress.i
  
  ; Zielverzeichnis sicherstellen
  If FileSize(dst) = -1
    CreateDirectory(dst)
  EndIf
  
  dir = ExamineDirectory(#PB_Any, src, "*.*")
  If dir
    While NextDirectoryEntry(dir)
      entry = DirectoryEntryName(dir)
      type  = DirectoryEntryType(dir)
      
      If type = #PB_DirectoryEntry_File
        fileSrc = src + "\" + entry
        fileDst = dst + "\" + entry
        
        dateSrc = GetFileDate(fileSrc, #PB_Date_Modified)
        dateDst = GetFileDate(fileDst, #PB_Date_Modified)
        
        If dateDst = 0 Or dateSrc > dateDst
          If CopyFile(fileSrc, fileDst)
            AddGadgetItem(5, -1, "Kopiert: " + fileDst)
          Else
            AddGadgetItem(5, -1, "FEHLER: " + fileDst)
          EndIf
        EndIf
        
        ; Fortschritt aktualisieren
        copiedFiles + 1
        progress = copiedFiles * 100 / totalFiles
        SetGadgetState(4, progress)                  ; Progressbar
        SetGadgetText(3, "Bearbeite: " + entry)      ; Status
        WindowEvent()                                ; UI aktualisieren
      ElseIf type = #PB_DirectoryEntry_Directory
        If entry <> "." And entry <> ".."
          CopyNewerFiles(src + "\" + entry, dst + "\" + entry)
        EndIf
      EndIf
    Wend
    FinishDirectory(dir)
  EndIf
EndProcedure

;---------------------------------
; Log in Datei speichern
;---------------------------------
Procedure SaveLog(filePath.s)
  Protected i, count
  
  count = CountGadgetItems(5)
  If count = 0
    MessageRequester("Info", "Es gibt kein Log zum Speichern.", #PB_MessageRequester_Ok)
    ProcedureReturn
  EndIf
  
  If CreateFile(0, filePath)
    For i = 0 To count - 1
      WriteStringN(0, GetGadgetItemText(5, i))
    Next
    CloseFile(0)
    MessageRequester("Info", "Log gespeichert unter: " + filePath, #PB_MessageRequester_Ok)
  Else
    MessageRequester("Fehler", "Konnte Log-Datei nicht erstellen.", #PB_MessageRequester_Ok)
  EndIf
EndProcedure

;---------------------------------
; Hauptprogramm mit GUI + Log + Pfadauswahl + INI
;---------------------------------
LoadSettings()

If OpenWindow(0, 100, 100, 650, 500, "Backup Tool", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  TextGadget(0, 10, 20, 100, 20, "Quelle:")
  StringGadget(1, 110, 20, 400, 20, src)
  ButtonGadget(10, 520, 20, 100, 20, "Auswählen")
  
  TextGadget(11, 10, 50, 100, 20, "Ziel:")
  StringGadget(2, 110, 50, 400, 20, dst)
  ButtonGadget(12, 520, 50, 100, 20, "Auswählen")
  
  ButtonGadget(13, 10, 80, 120, 30, "Backup starten")
  ButtonGadget(14, 150, 80, 120, 30, "Log speichern")
  
  StringGadget(3, 10, 120, 630, 25, "Status: bereit", #PB_String_ReadOnly)
  ProgressBarGadget(4, 10, 160, 630, 20, 0, 100, #PB_ProgressBar_Smooth)
  ListViewGadget(5, 10, 190, 630, 280)   ; Log-Ausgabe
  
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 10 ; Quelle auswählen
            src = PathRequester("Quellordner auswählen", GetGadgetText(1))
            If src <> ""
              SetGadgetText(1, src)
            EndIf
            
          Case 12 ; Ziel auswählen
            dst = PathRequester("Zielordner auswählen", GetGadgetText(2))
            If dst <> ""
              SetGadgetText(2, dst)
            EndIf
            
          Case 13 ; Backup starten
            src = GetGadgetText(1)
            dst = GetGadgetText(2)
            
            If src = "" Or dst = ""
              MessageRequester("Fehler", "Bitte Quelle und Ziel auswählen!", #PB_MessageRequester_Ok)
            Else
              SaveSettings() ; letzte Pfade sichern
              
              ClearGadgetItems(5)
              SetGadgetText(3, "Zähle Dateien...")
              copiedFiles = 0
              totalFiles  = CountFiles(src)
              
              If totalFiles > 0
                SetGadgetText(3, "Starte Backup...")
                SetGadgetState(4, 0)
                
                CopyNewerFiles(src, dst)
                AddGadgetItem(5, -1, "--- Backup abgeschlossen ---")
                SetGadgetText(3, "Backup abgeschlossen! (" + Str(totalFiles) + " Dateien geprüft)")
              Else
                SetGadgetText(3, "Keine Dateien gefunden.")
              EndIf
            EndIf
            
          Case 14 ; Log speichern
            If dst <> ""
              SaveLog(dst + "\BackupLog.txt")
            Else
              Define filePath.s = SaveFileRequester("Log speichern unter...", "BackupLog.txt", "Textdateien|*.txt", 0)
              If filePath <> ""
                SaveLog(filePath)
              EndIf
            EndIf
        EndSelect
        
      Case #PB_Event_CloseWindow
        Break
    EndSelect
  ForEver
EndIf

Ist jetzt nichts Großes, gibt es wahrscheinlich schon mehrfach in den Foren. Hat mich trotzdem beeindruckt.

Freue mich über Rückmeldungen.
Zuletzt geändert von stab am 05.10.2025 12:26, insgesamt 2-mal geändert.
Paul sagt: "Max lügt."
Max sagt: "Otto lügt."
Otto sagt: "Max und Paul lügen."

Wer lügt hier wirklich und wer sagt die Wahrheit?

_________________________________________

286er Big Tower; 16MHz; 1MB Ram; 40MB Festplatte, 5 1/4" und 3 1/2" Diskettenlaufwerk; VGA Farbmonitor 14"; Windows 3.1; PureBasic 0.5
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7032
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Verwendung von PB mit KI

Beitrag von STARGÅTE »

Hallo stab,

ich selbst programmiere weiterhin ohne KI. Ich empfinde es aktuell immer noch aufwendiger der KI mit geeigneten Prompts klar zu machen, was man will, wie man es will und im nachhinein trotzdem den Code noch mal Zeile für Zeile nach Bugs zu durchforsten, gerade bei Nischensprachen wie PureBasic. Ganz zu schweige von den rechtlichen Bedenken (Datenschutz, Urheberrechte), was mit meinen Prompts passiert und woher die Code-Fragmente kommen. Ich gebe zu, beim Thema KI bin ich etwas konservativ und schreibe meinen code selbst und lese Dokus und Foren.

Zu deinem Code selbst habe ich folgende Kommentare:
  • Auch wenn OpenPreferences() fehlschlägt (weil die Datei nicht exzitiert), können die Lesebefehle verwendet werden, weil dann nämlich auf die Default-Werte zurückgegriffen wird, die man bei ReadPreference...() angeben kann.
  • Für den Pfadseparator (in Windows "\") kann man #PS$ verwenden, um so auch die Kompatibilität mit anderen Betriebssystemen zu gewährleisten.
  • Die Verwendung von WindowEvent() mitten im Code, um die "UI [zu] aktualisieren" ist eine schlechte Angewohnheit. Klar wird die Oberfläche aktualisiert, aber weil das Event gar nicht verarbeitet wird, gehen viele wichtige Events einfach verloren, w.z.B. das Fensterschließen.
    Wenn eine Kopier-Schleife die Event-Schleife wirklich lange pausiert, sollte man überlegen mit Threads und PostEvent() zu arbeiten.
  • Die beiden PathRequester() geben einen leeren String zurück, auch wenn der Requester geschlossen wird. Dann wird natürlich auch "src" und "dst" geleert, aber wegen der Abfrage danach nicht die GUI geändert. Da aber bei CopyNewerFiles(src, dst) die Variable genutzt wird, und nicht der Inhalt des Text-Gadgets, würde man aus oder in einem anderen Pfad kopieren als im Fenster steht, sehr gefährlich!
  • Die Gadgets alle mit Zahlen anzusprechen ist zwar möglich, aber die Verwendung von Enumeration mit Konstanten würde die Lesbarkeit deutlich erhöhen und Fehler Vermeiden.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
stab
Beiträge: 99
Registriert: 24.02.2006 16:09
Computerausstattung: 286er Big Tower; 16MHz; 1MB Ram; 40MB Festplatte, 5 1/4" und 3 1/2" Diskettenlaufwerk; VGA Farbmonitor 14"; Windows 3.1; PureBasic 0.5
Wohnort: Hardt
Kontaktdaten:

Re: Verwendung von PB mit KI - und Frage zu WindowEvent

Beitrag von stab »

Hallo STARGÅTE,

danke für deine Einschätzung.

Der KI klarzumachen, was ich wollte, ging in diesem Fall wirklich sehr schnell. Wenn ich bedenke, wie lange ich manchmal benötige, allein ein passendes GUI zu basteln, fand ich die Zeitersparnis schon beeindruckend. Zumindest für mich, als Gelegenheitsprogrammierer.
Zu deinem Code selbst habe ich folgende Kommentare:
Dies war ja nicht mein Code, sondern so wie er da steht, wurde er von der KI erzeugt. Eigentlich habe ich den Code nur überflogen und mich auf das Ergebnis konzentriert. Nach deinen Einwendungen habe ich aber jetzt wirklich dazu eine Frage. Es geht um Zeile 188.

Code: Alles auswählen

SetGadgetText(3, "Zähle Dateien...")
Die Änderung des Textes erfolgt ja nicht nach StartKlick, so wie es wohl gewollt ist. Deshalb passiert erstmal für den Betrachter nichts.
Das scheint ja mit den WindowEvents zusammenzuhängen.

Dazu das sehr vereinfachte Beispiel:
Vielleicht gehört das Ganze ja auch in die Anfängergruppe. Ich wundere mich nur, dass ich bisher nie ein Problem damit hatte.

Code: Alles auswählen

;
; This code is automatically generated by the Form Designer.
; Manual modification is possible to adjust existing commands, but anything else will be dropped when the code is compiled.
; Event procedures need to be put in another source file.
;

Enumeration FormWindow
  #Window_0
EndEnumeration

Enumeration FormGadget
  #Button_0
  #String_0
EndEnumeration

Procedure OpenWindow_0(x = 0, y = 0, width = 600, height = 400)
  OpenWindow(#Window_0, x, y, width, height, "", #PB_Window_SystemMenu | #PB_Window_SystemMenu)
  ButtonGadget(#Button_0, 230, 210, 100, 25, "Klick")
  StringGadget(#String_0, 180, 120, 250, 25, "String")
EndProcedure

Procedure irgendwas()
    For d =1 To 5 : Delay(500) : Debug d : Next
EndProcedure

Procedure Window_0_Events(event)
  
  Select event
    Case #PB_Event_CloseWindow
      End 
    Case #PB_Event_Gadget
      
      Select EventGadget()
        Case #Button_0
          SetGadgetText(#string_0, "es wurde geklickt")
          irgendwas()
      EndSelect
  EndSelect         
 
EndProcedure

OpenWindow_0()

Repeat
  
  event = WaitWindowEvent()
  
  If event
    Window_0_Events(event)
  EndIf
 
ForEver

Warum wird SetGadgetText (Zeile 35) nicht vor Aufruf der Funktion ausgeführt?
Bzw., wie kann ich erreichen, dass SetGadgetText in diesem Beispiel vor Aufruf der Funktion ausgeführt wird?

Irgendwie habe ich ein Brett vor dem Kopf.
Paul sagt: "Max lügt."
Max sagt: "Otto lügt."
Otto sagt: "Max und Paul lügen."

Wer lügt hier wirklich und wer sagt die Wahrheit?

_________________________________________

286er Big Tower; 16MHz; 1MB Ram; 40MB Festplatte, 5 1/4" und 3 1/2" Diskettenlaufwerk; VGA Farbmonitor 14"; Windows 3.1; PureBasic 0.5
Benutzeravatar
Bisonte
Beiträge: 2470
Registriert: 01.04.2007 20:18

Re: Verwendung von PB mit KI - und Frage zu WindowEvent

Beitrag von Bisonte »

SetGadgetText löst eine Aktion aus, die erst angezeigt wird, sobald du dem Fenster wieder die Möglichkeit gibst,
das ganze auch anzuzeigen. Das passiert beim nächsten "WaitWindowEvent()".
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
Benutzeravatar
stab
Beiträge: 99
Registriert: 24.02.2006 16:09
Computerausstattung: 286er Big Tower; 16MHz; 1MB Ram; 40MB Festplatte, 5 1/4" und 3 1/2" Diskettenlaufwerk; VGA Farbmonitor 14"; Windows 3.1; PureBasic 0.5
Wohnort: Hardt
Kontaktdaten:

Re: Verwendung von PB mit KI - und Frage zu WindowEvent

Beitrag von stab »

Ich bin jetzt auf den Trichter gekommen.
Sorry, war wieder eine ganze Zeit draußen.
Danke auch.

Code: Alles auswählen

;
; This code is automatically generated by the Form Designer.
; Manual modification is possible to adjust existing commands, but anything else will be dropped when the code is compiled.
; Event procedures need to be put in another source file.
;

Enumeration FormWindow
  #Window_0
EndEnumeration

Enumeration FormGadget
  #Button_0
  #String_0
EndEnumeration

Procedure OpenWindow_0(x = 0, y = 0, width = 600, height = 400)
  OpenWindow(#Window_0, x, y, width, height, "", #PB_Window_SystemMenu | #PB_Window_SystemMenu)
  ButtonGadget(#Button_0, 230, 210, 100, 25, "Klick")
  StringGadget(#String_0, 180, 120, 250, 25, "String")
EndProcedure

Procedure irgendwas(t)
    For d =1 To 5 : Delay(500) : Debug d : Next
EndProcedure

Procedure Window_0_Events(event)
  
  Select event
    Case #PB_Event_CloseWindow
      End 
    Case #PB_Event_Gadget
      
      Select EventGadget()
        Case #Button_0
          SetGadgetText(#string_0, "es wurde geklickt")
          CreateThread(@irgendwas(),1)
      EndSelect
  EndSelect         
 
EndProcedure

OpenWindow_0()

Repeat
  
  event = WaitWindowEvent()
  
  If event
    Window_0_Events(event)
  EndIf
 
ForEver


Paul sagt: "Max lügt."
Max sagt: "Otto lügt."
Otto sagt: "Max und Paul lügen."

Wer lügt hier wirklich und wer sagt die Wahrheit?

_________________________________________

286er Big Tower; 16MHz; 1MB Ram; 40MB Festplatte, 5 1/4" und 3 1/2" Diskettenlaufwerk; VGA Farbmonitor 14"; Windows 3.1; PureBasic 0.5
Antworten