Disegnare in una DrawingArea dei punti

Da Gambas-it.org - Wikipedia.
Versione del 4 giu 2023 alle 08:07 di Vuott (Discussione | contributi) (Creata pagina con "=Istruzioni fondamentali per disegnare un punto su una ''DrawingArea''= Per disegnare da codice dei punti su una ''DrawingArea'', si potrà fare uso del Metodo ".Arc()" o del...")

(diff) ← Versione meno recente | Versione attuale (diff) | Versione più recente → (diff)

Istruzioni fondamentali per disegnare un punto su una DrawingArea

Per disegnare da codice dei punti su una DrawingArea, si potrà fare uso del Metodo ".Arc()" o del Metodo ".Ellipse" della Classe Paint.

Mostriamo un semplice esempio, nel quale si mostrerà luso dei due predetti Metodi:

Public Sub Form_Open()

 With Me
   .W = Screen.AvailableWidth
   .H = Screen.AvailableHeight
   .Arrangement = Arrange.Fill
 End With
 With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
   .Background = Color.White
 End With

End

Public Sub DrawingArea1_Draw()

 With Paint
   .Brush = .Color(Color.Red)
   .Arc(200, 200, 2, Rad(0), Rad(360), False)
   .Fill
   .Brush = .Color(Color.Blue)
   .Ellipse(400, 400, 2, 2, Rad(0), Rad(360), False)
   .Fill
   .End
 End With

End


Disegnare in successione dei punti in una DrawingArea

Visibile soltanto il punto corrente disegnato usando la Classe Paint

In questo caso si utilizzerà la Classe Paint e verrà mostrato soltanto il nuovo punto disegnato: quelli precedentemente disegnati non saranno più visibili.

Nell'esempio che segue, ruotando la rotellina del mouse avanti o indietro sulla DrawingArea saranno mostrati in successione dei punti lungo la circonferenza di un cerchio predefinito dal codice. L'effetto visivo ottenuto, sarà quello di un punto che si sposta lungo una circonferenza immaginaria.

Private DrawingArea1 As DrawingArea
Private Const PASSO As Byte = 2
Private t As Short


Public Sub _new()

 With Me
   .W = Screen.AvailableWidth
   .H = Screen.AvailableHeight
   .Arrangement = Arrange.Fill
 End With
 With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
   .Background = Color.White
 End With

End

Public Sub DrawingArea1_MouseWheel()
 
 t += (Mouse.Delta) + (PASSO * Mouse.Delta)
 
 DrawingArea1.Refresh
 
End

Public Sub DrawingArea1_Draw()
 
 Dim x, y, r As Short
 
 x = DrawingArea1.W / 2
 y = DrawingArea1.H / 2
 r = 100
 
 With Paint
   .Brush = .Color(Color.Red)
   .Arc(x + (r * Cos(Rad(t))), y + (r * Sin(Rad(t))), 2, Rad(0), Rad(360), False)
   .Fill
   .End
 End With
 
End

Con l'uso del Timer

In quest'altro caso imporremo un ritardo temporale nel disegno dei punti con l'uso dell'oggetto Timer:

Private DrawingArea1 As DrawingArea
Private Timer1 As Timer
Private c As Short


Public Sub _new()

 With Me
   .W = Screen.AvailableWidth * 0.7
   .H = Screen.AvailableHeight * 0.75
 End With
 With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
   .X = 0
   .Y = Me.H * 0.15
   .W = Me.Width
   .H = Me.H * 0.7
   .Background = &FFFFBF
 End With
 With Timer1 = New Timer As "Timer1"
   .Delay = 500   ' Ritardo = 0,5 secondi
 End With

End

Public Sub Form_Open()

 With Me
   .Center
   .Y = Screen.AvailableHeight * 0.1
 End With

 Timer1.Start
  
End

Public Sub Timer1_Timer()
 
 DrawingArea1.Refresh()
 
End

Public Sub DrawingArea1_Draw()

 Dim i As Short
 
 i = 50 * c
 
 With Paint
   .FillRect(i, 100, 3, 3, Color.Red)
   .End
 End With
 
 Inc c
 
 If i > DrawingArea1.W Then c = 0
 
End

Il punto percorre una traiettoria sinusoidale

In quest'altro esempio usando il Timer il punto percorrerà una traiettoria sinusoidale:

Private DrawingArea1 As DrawingArea
Private Timer1 As Timer
Private Const FREQUENZA As Float = 440.0
Private w As Short
Private t As Short


Public Sub _new()

 With Me
   .W = Screen.AvailableWidth
   .H = Screen.AvailableHeight
   .Arrangement = Arrange.Fill
 End With
 With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
   .Background = &FFFFBF
 End With
 With Timer1 = New Timer As "Timer1"
   .Delay = 10   ' Ritardo = 0,01 secondi
 End With

 w = DrawingArea1.W

End

Public Sub Form_Open()

 With Me
   .Center
   .Y = Screen.AvailableHeight * 0.1
 End With

 Timer1.Start
  
End

Public Sub Timer1_Timer()

 Dec w
 If w == 0 Then w = DrawingArea1.W
 
 DrawingArea1.Refresh()

End

Public Sub DrawingArea1_Draw()
 
 Dim y As Short
 Dim d As Short
 
 Inc t
 
' s = A * sin(2π*(1/T)*t)
' https://www.youtube.com/watch?v=YijlJ2Ekj4k
 y = DrawingArea1.H / 2 * Sin(((2 * Pi) * (1 / FREQUENZA)) * t) 
 
' Centra l'onda nel mezzo della "DrawingArea":
 y += DrawingArea1.H / 2
 
 d = Ceil(DrawingArea1.W / DrawingArea1.Font.TextWidth("- ")) + 2
 
 With Paint
   .FillRect(w, y, 4, 4, Color.Red)
   .DrawText(String(d, "- "), 0, DrawingArea1.H / 2, d, 3, Align.Left)
   .End
 End With
 
End

Usando un ciclo

Invece dell'Oggetto "Timer" si potrà usare anche un ciclo.

Il punto percorre una traiettoria sinusoidale

Private DrawingArea1 As DrawingArea
Private Const AMPIEZZA As Float = 100.0
Private Const FREQUENZA As Float = 440.0
Private t As Integer
Private x As Integer


Public Sub Form_Open()  

 With Me
   .W = Screen.AvailableWidth
   .H = Screen.AvailableHeight
   .Arrangement = Arrange.Fill
 End With  

 With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
   .Background = Color.White
 End With

End

Public Sub DrawingArea1_MouseUp()

 Do
   Inc x
   If x > DrawingArea1.w Then x = 0
   DrawingArea1.Refresh
   Wait 0.01
 Loop

End

Public Sub DrawingArea1_Draw()
 
 Dim y, f As Float

 f = 1 / FREQUENZA
 Inc t
 y = AMPIEZZA * Sin(2 * Pi * f * t)
' Centra l'onda nel mezzo della "DrawingArea":
 y += DrawingArea1.H / 2
 With Paint
   .FillRect(x, y, 4, 4, Color.Red)
   .End
 End With
 
End

Altri tipi di esempi

In quest'altro esempio verrà disegnato un punto rosso che mediante l'uso della funzione "Cos()" si sposterà in orizzontale oscillando da un estremo all'altro della DrawingArea.

Private DrawingArea1 As DrawingArea
Private f As Float


Public Sub Form_Open()

 Dim c As Short

 With Me
   .W = Screen.AvailableWidth
   .H = Screen.AvailableHeight
   .Arrangement = Arrange.Fill
 End With
 With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
   .Background = Color.SoftYellow
 End With
 Me.Show

' Esegue un ciclo infinito sin tanto che l'Oggetto "DrawingArea" è valido: se la finestra del "Form" viene chiusa, allora l'Oggetto "DrawingArea" viene distrutto e, non essendo esso più valido, si esce dal ciclo:
 While Object.IsValid(DrawingArea1) 
   f = Cos(Rad(c)) * (DrawingArea1.W / 2)
   DrawingArea1.Refresh
   Wait 0.01
   Inc c
   If c == 360 Then c = 0
 Wend

End

Public Sub DrawingArea1_Draw()

 With Paint
   .Brush = .Color(Color.Red)
   .Arc(f + (DrawingArea1.W / 2), DrawingArea1.H / 2, 2, Rad(0), Rad(360), False)
   .Fill
   .End
 End With

End


In questo esempio nella DrawingArea verrà disegnato un punto che, partendo da coordinate x,y iniziali, dovrà raggiungere - spostandosi poco alla volta - altrettante coordinate di destinazione.

Private DrawingArea1 As DrawingArea
Private p As Short[] = [410, 430]       ' Imposta le coordinate di partenza del punto mobile
Private arrivo As Short[] = [320, 480]  ' Imposta le coordinate di destinazione del punto mobile
Private b As Byte = 1


Public Sub _new()

 With Me
   .W = Screen.AvailableWidth
   .H = Screen.AvailableHeight
   .Arrangement = Arrange.Fill
 End With
 With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
   .Background = Color.Lighter(Color.Yellow)
 End With

End

Public Sub Form_Open()

 Me.Show
 Wait 1

 Repeat 
   If p[0] > arrivo[0] Then p[0] -= 1
   If p[0] < arrivo[0] Then p[0] += 1
   If p[1] > arrivo[1] Then p[1] -= 1
   If p[1] < arrivo[1] Then p[1] += 1
   Me.Text = "X = " & CStr(p[0]) & " Y = " & CStr(p[1]) &
             "   Arrivo: " & CStr(arrivo[0]) & "," & CStr(arrivo[1])
   If (p[0] == arrivo[0]) And (p[1] == arrivo[1]) Then b = 2
   DrawingArea1.Refresh
' Usando un ciclo, avere cura di porre un tempo, seppur minimo, di attesa, per non utilizzare eccessivamente le risorse:
   Wait 0.1
 Until (p[0] == arrivo[0]) And (p[1] == arrivo[1])  ' Si esce dal ciclo, quando il punto avrà raggiunto le coordinate di destinazione

End

Public Sub DrawingArea1_Draw()

 With Paint
   .Brush = .Color(Color.Red)
   .Arc(p[0], p[1], b, Rad(0), Rad(360), False)
   .Fill
   .End
 End With

End


Visibili il punto corrente disegnato e tutti i punti precedentemente disegnati

In quest'altro caso, invece, resteranno visibili tutti i punti precedentemente disegnati e descriveranno andamento sinusoidale:

Public Sub DrawingArea1_Draw()
 
 Dim x, y As Short
 
 With Paint
   .Brush = .Color(Color.Red)
   For x = 1 To 360
     y = DrawingArea1.H / 2 * Sin(((2 * Pi) * (1 / 100)) * x)
' Centriamo il disegno dell'onda rispetto all'altezza della "DrawingArea":
     y += DrawingArea1.H / 2
     .Arc(x, y, 1.5, Rad(0), Rad(360), False)
     .Fill
   Next
   .End
 End With

End


In quest'altro esempio sarà usato il Metodo ".FillRect()" della Classe Paint e, per imporre il ritardo temporale nel disegno dei punti useremo il Timer.

Private DrawingArea1 As DrawingArea
Private Timer1 As Timer
Private pnt As Short[]
Private d As Short

Public Sub _new()

 With Me
   .W = Screen.AvailableWidth
   .H = Screen.AvailableHeight
   .Arrangement = Arrange.Fill
 End With
 With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
   .Background = Color.White
 End With

End

Public Sub Form_Arrange()  

 pnt = New Short[]

 With Timer1 = New Timer As "Timer1"
   .Delay = 500   ' Ritardo = 1/2 secondo
   .Start()
 End With

End

Public Sub Timer1_Timer()
 
 DrawingArea1.Refresh()
 
End

Public Sub DrawingArea1_Draw()
 
 Dim c As Short
 
 With Paint
   For c = 0 To pnt.Max
     .FillRect(pnt[c], DrawingArea1.H / 2, 3, 3, Color.Red)
   Next
   .End
 End With
 
 d += 4
 pnt.Push(d)
 d += 4
 
End

Disegnare punto per punto una Spirale di Archimede

In quest'altro esempio verrà riprodotta una Spirale di Archimede: [nota 1]

Private DrAr As DrawingArea
Private Const A As Float = 4.0
Private Const B As Float = 4.0
Private Const KYKLOS As Float = 26.0
Private Const PASSI As Integer = 200
Private incr As Float = 1.0 / PASSI
 
 
Public Sub Form_Open()

 With Me
   .W = Screen.AvailableWidth
   .H = Screen.AvailableHeight
   .Arrangement = Arrange.Fill
 End With
 With DrAr = New DrawingArea(Me) As "DrawingArea1"
   .Background = Color.White
 End With
    
End

Public Sub DrawingArea1_Draw()
 
 Dim x, y As Integer
 Dim i As Float
    
 x = DrAr.W / 2
 y = DrAr.H / 2
    
 With Paint
   .Brush = .Color(Color.Red)
   While i <= KYKLOS * Pi
     .Arc(x + (A + B * i) * Cos(i), y + (A + B * i) * Sin(i), 0.8, Rad(0), Rad(360), False)
     .Fill
     i += incr
   Wend
   .End
 End With
    
End

Disegnare punto per punto un cerchio

In quest'altro esempio, conoscendo raggio e centro della circonferenza, nonché il relativo angolo, è possibile disegnare un cerchio, o parte di esso disegnandolo punto per punto mediante una formula trigonometrica.:
Da notare che la seguente impostazione:

x + (r * Cos(Rad(t))) 
y + (r * Sin(Rad(t)))

disegnerà l'arco in senso orario;
la seguente impostazione:

x + (r * Cos(Rad(t))) 
y - (r * Sin(Rad(t)))

disegnerà l'arco in senso orario.

Provare anche le altre due possibilità:

x - (r * Cos(Rad(t))) 
y - (r * Sin(Rad(t)))

e

x - (r * Cos(Rad(t))) 
y + (r * Sin(Rad(t)))

Sarà utilizzato il Metodo "Paint.Arc()" per creare i punti:

Public Sub DrawingArea1_Draw()
 
 Dim x, y, r, t As Short
 
 x = DrawingArea1.W / 2
 y = DrawingArea1.H / 2
 r = 100
 
 With Paint
   .Brush = .Color(Color.Red)
   For t = 0 To 360
     .Arc(x + (r * Cos(Rad(t))), y + (r * Sin(Rad(t))), 1.0, Rad(0), Rad(360), False)
   Next
   .Fill
   .End
 End With
  
End


Note

[1] Vedere anche questa pagina: Disegnare in una DrawingArea una spirale di Archimede