Einsteiger-Kapitel - Anzeigen von Grafik-Ausgabe & einfaches Zeichnen

Dieses Beispiel zeigt, wie man eine einfache Zeichnung erstellt. Es verwendet die 2D Zeichenbefehle zum Zeichnen von zwei Sinuskurven mit verschiedenen Frequenzen und zeigt die durch die Kombination der beiden Wellen hergestelte "Harmonie". Es verwendet Prozeduren, welche wir uns später im Detail anschauen werden, um die Zeichenaufgaben in drei in sich abgeschlossene Aufgaben aufzuteilen:

Zeichnen der Achsen - demonstriert den Line() Befehl.
Zeichnen der Legende - demonstriert die Box() und DrawText() Befehle.
Zeichnen der Wellen - demonstriert den LineXY() Befehl und zeigt die Verwendung von Farben.
  ; Fenster
  Enumeration
    #WinHarmonic
  EndEnumeration
  
  ; Gadgets
  Enumeration
    #txtPlot1
    #cboPlot1
    #txtPlot2
    #cboPlot2
    #imgPlot
  EndEnumeration
  
  ; Bild (Image)
  Enumeration
    #drgPlot
  EndEnumeration
  
  ; Die Bild-Abmessungen werden an verschiedenen Stellen zum Definieren weiterer Werte genutzt.
  #imgPlotX = 8
  #imgPlotY = 40
  #imgPlotW = 745
  #imgPlotH = 645

  ; Ereignis-Variablen
  Define.l Event, EventWindow, EventGadget, EventType, EventMenu
  
  ; Implementierung
  Procedure CreateWindow()
    ; Erstellt das Fenster und die Gadgets.
    
    If OpenWindow(#WinHarmonic, 30, 30, #imgPlotW + 20, #imgPlotH + 55, "Harmonics", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_TitleBar)
      
      ; Dies ist ein nicht sichtbares Image, welches zum Zeichnen des Bildes verwendet wird,
      ; später wird sein Inhalt in #imgPlot dargestellt.
      CreateImage(#drgPlot, #imgPlotW - 5, #imgPlotH - 5, 24)
      
      ; Beschriftung für die Plot 1 Auswahlbox.
      TextGadget(#txtPlot1, 2, 5, 50, 25, "Plot 1:")
      
      ; Die Plot 1 Auswahlbox.
      ComboBoxGadget(#cboPlot1, 55, 5, 150, 25)
      AddGadgetItem(#cboPlot1, 0, "Sin(X)")
      AddGadgetItem(#cboPlot1, 1, "Sin(X * 2)")
      AddGadgetItem(#cboPlot1, 2, "Sin(X * 3)")
      AddGadgetItem(#cboPlot1, 3, "Sin(X * 4)")
      AddGadgetItem(#cboPlot1, 4, "Sin(X * 5)")
      AddGadgetItem(#cboPlot1, 5, "Sin(X * 6)")
      
      ; Auswählen von Sin(X)
      SetGadgetState(#cboPlot1, 0)
      
      ; Beschriftung für die Plot 2 Auswahlbox.
      TextGadget(#txtPlot2, 230, 5, 50, 25, "Plot 2:")
      
      ; Die Plot 2 Auswahlbox.
      ComboBoxGadget(#cboPlot2, 280, 5, 150, 25)
      AddGadgetItem(#cboPlot2, 0, "Sin(X)")
      AddGadgetItem(#cboPlot2, 1, "Sin(X * 2)")
      AddGadgetItem(#cboPlot2, 2, "Sin(X * 3)")
      AddGadgetItem(#cboPlot2, 3, "Sin(X * 4)")
      AddGadgetItem(#cboPlot2, 4, "Sin(X * 5)")
      AddGadgetItem(#cboPlot2, 5, "Sin(X * 6)")
      
      ; Auswählen Sin(X * 2), andernfalls ist die anfängliche Darstellung ziemlich uninteressant.
      SetGadgetState(#cboPlot2, 1)
      
      ; Das sichtbare Bild-Gadget auf dem Fenster.
      ImageGadget(#imgPlot, #imgPlotX, #imgPlotY, #imgPlotW, #imgPlotH, 0, #PB_Image_Border)
      
    EndIf
  EndProcedure
  
  Procedure PlotAxes()
    ; Zeichnet die Achsen auf dem Bild #drgPlot.
    
    ; Sendet Zeichenbefehle an #drgPlot.
    StartDrawing(ImageOutput(#drgPlot))
    
      ; Zeichnet einen weißen Hintergrund.
      Box(0, 0, ImageWidth(#drgPlot), ImageHeight(#drgPlot), RGB(255, 255, 255))
      
      ; Zeichnet die Achsen in schwarz.
      Line(1, 1, 1, ImageHeight(#drgPlot) - 2, RGB(0, 0, 0))
      Line(1, (ImageHeight(#drgPlot) - 2) /2, ImageWidth(#drgPlot) -2, 1, RGB(0, 0, 0))
      
      ; Zeichnen abschließen.
    StopDrawing()
  EndProcedure
  
  Procedure PlotLegend(alngPlot1, alngPlot2)
    ; Zeichnet die Legende auf dem Bild #drgPlot.
    
    Protected.s strFunc1, strFunc2, strLabel1, strLabel2, strLabel3
    
    ; Legt den Beschriftungs-Text 1 fest.
    If alngPlot1 = 0 
      strFunc1 = "Sin(X)"
    Else
      strFunc1 = "Sin(X * " + StrU(alngPlot1 + 1) + ")"
    EndIf
    
    ; Legt den Beschriftungs-Text 2 fest.
    If alngPlot2 = 0 
      strFunc2 = "Sin(X)"
    Else
      strFunc2 = "Sin(X * " + StrU(alngPlot2 + 1) + ")"
    EndIf
    
    ; Legt den Beschriftungs-Text fest.
    strLabel1 = "Y = " + strFunc1
    strLabel2 = "Y = " + strFunc2
    strLabel3 = "Y = " + strFunc1 + " + " + strFunc2 
    
    ; Zeichnet die Legende.
    StartDrawing(ImageOutput(#drgPlot))
    
      ; Box.
      DrawingMode(#PB_2DDrawing_Outlined)
      Box(20, 10, TextWidth(strLabel3) + 85, 80, RGB(0, 0, 0))
      
      ; Beschriftung 1.
      Line(30, 30, 50, 1, RGB(0, 0, 255))
      DrawText(95, 22, strLabel1, RGB(0, 0, 0), RGB(255, 255, 255))
      
      ; Beschriftung 2.
      Line(30, 50, 50, 1, RGB(0, 255, 200))
      DrawText(95, 42, strLabel2, RGB(0, 0, 0), RGB(255, 255, 255))
      
      ; Beschriftung 3.
      Line(30, 70, 50, 1, RGB(255, 0, 0))
      DrawText(95, 62, strLabel3, RGB(0, 0, 0), RGB(255, 255, 255))
      
    StopDrawing()
  EndProcedure
  
  Procedure PlotFunction(alngPlot1, alngPlot2)
    ; Zeichnet die Wellenformen auf das Bild #drgPlot.
    
    Protected.l lngSX, lngEX
    Protected.f fltRad1, fltRad2, fltSY1, fltEY1, fltSY2, fltEY2, fltSY3, fltEY3
    
    StartDrawing(ImageOutput(#drgPlot))
      
      ; Legt die anfänglichen Start-Punkte für jede Welle fest.
      lngSX = 1
      fltSY1 = ImageHeight(#drgPlot) / 2
      fltSY2 = fltSY1
      fltSY3 = fltSY1
      
      ; Zeichnet die Wellenformen.
      For lngEX = 1 To 720
        ; Die Sinus-Funktion arbeitet im Bogenmaß, daher konvertieren von Grad und berechnen den Sinus.
        
        ; Funktion 1
        If alngPlot1 = 0 
          fltRad1 = Sin(Radian(lngEX))
        Else
          ; Wenn die Funktion einen Multiplikator haben sollte, beachten wir dies.
          fltRad1 = Sin(Radian(lngEX) * (alngPlot1 + 1))
        EndIf
        
        ; Funktion 2
        If alngPlot2 = 0 
          fltRad2 = Sin(Radian(lngEX))
        Else
          fltRad2 = Sin(Radian(lngEX) * (alngPlot2 + 1))
        EndIf
        
        ; Zeichnen der Funktion 1 in blau.
        ; Berechnen des Y Endpunkts.
        fltEY1 = (ImageHeight(#drgPlot) / 2) + (fltRad1 * 100)
        ; Zeichnen einer Linie vom Startpunkt zum Endpunkt.
        LineXY(lngSX, fltSY1, lngEX, fltEY1, RGB(0, 0, 255))
        ; Aktualisieren des nächsten Y Startpunkts, damit dieser den aktuellen Y Endpunkt übernimmt.
        fltSY1 = fltEY1
        
        ; Zeichnen der Funktion 2 in grün.
        fltEY2 = (ImageHeight(#drgPlot) / 2) + (fltRad2 * 100)
        LineXY(lngSX, fltSY2, lngEX, fltEY2, RGB(0, 255, 200))
        fltSY2 = fltEY2
      
        ; Zeichnen der Harmonie in rot.
        fltEY3 = (ImageHeight(#drgPlot) / 2) + ((fltRad1 + fltRad2) * 100)
        LineXY(lngSX, fltSY3, lngEX, fltEY3, RGB(255, 0, 0))
        fltSY3 = fltEY3
        
        ; Aktualisieren des X Startpunkts, damit dieser den aktuellen X Endpunkt übernimmt.
        lngSX = lngEX
      Next lngEX
      
    StopDrawing()
    
  EndProcedure
  
  ;- Main
  CreateWindow()
  PlotAxes()
  PlotLegend(GetGadgetState(#cboPlot1), GetGadgetState(#cboPlot2))
  PlotFunction(GetGadgetState(#cboPlot1), GetGadgetState(#cboPlot2))
  
  ; Neu laden des Image Gadgets, da das Zeichnen nun komplett ist.
  ImageGadget(#imgPlot, #imgPlotX, #imgPlotY, #imgPlotW, #imgPlotH, ImageID(#drgPlot), #PB_Image_Border)
  
  ;- Ereignis-Schleife
  Repeat
    Event = WaitWindowEvent()
    EventWindow = EventWindow()
    EventGadget = EventGadget()
    EventType = EventType()
    
    Select Event
      Case #PB_Event_Gadget
        If EventGadget = #txtPlot1 Or EventGadget = #txtPlot2
          ; Tue nichts.
        ElseIf EventGadget = #imgPlot
          ; Tue nichts.
        ElseIf EventGadget = #cboPlot1 Or EventGadget = #cboPlot2
          ; Wenn eine der Auswahlboxen verändert wurde, zeichnen wir das Bild erneut.
          PlotAxes()
          PlotLegend(GetGadgetState(#cboPlot1), GetGadgetState(#cboPlot2))
          PlotFunction(GetGadgetState(#cboPlot1), GetGadgetState(#cboPlot2))
          ImageGadget(#imgPlot, #imgPlotX, #imgPlotY, #imgPlotW, #imgPlotH, ImageID(#drgPlot), #PB_Image_Border)
        EndIf
      Case #PB_Event_CloseWindow
        If EventWindow = #WinHarmonic
          CloseWindow(#WinHarmonic)
          Break
        EndIf
    EndSelect
  ForEver

Einsteiger-Kapitel Navigation

< Vorheriges: Erstellen einer grafischen Benutzeroberfläche (GUI) | Überblick | Nächstes: Strukturieren von Programmcode in Prozeduren >