9.1.- FUNDAMENTOS DE LOS GRÁFICOS. ESCALAS DE LA PANTALLA.
INTRODUCCIÓN.
Lo que se puede hacer con las sentencias gráficas, depende de los controladores que Windows emplee para controlar la pantalla y la impresora. Sin embargo, el uso de estos controladores es automático. A menos que se establezca la propiedad AutoRedraw del formulario a True, será necesario gestionar el volver a dibujar los gráficos. Cuando esta propiedad está a True, se crea una copia del objeto en memoria para poder reproducir automáticamente los dibujos pintados con métodos gráficos cuando la ventana cambia de tamaño o es ocultada total o parcialmente por otra ventana. Esta operación tiene un coste de memoria. Si la propiedad tiene un valor False, los gráficos no serán reproducidos. Visual Basic activa el suceso Paint cada vez que se visualiza un formulario o una parte nueva del mismo. Si la propiedad ClipControls, que determina si los métodos gráficos contenidos en un procedimiento conducido por el suceso Paint perteneciente a un objeto, repintan el objeto entero o solo la parte que se vuelve a visualizar. Si está a False y AutoRedraw a False, Visual Basic vuelve a pintar sólo el área que se muestra nueva. Sólo se llama al procedimiento Paint cuando la propiedad AutoRedraw está a False.
EJEMPLOS:
Sub Form_Load()
Print "Por favor, Haz clic para una demostración de AutoRedraw"
Print "Estas dos líneas permanecerán en la pantalla después de hacer doble clic"
End Sub
Sub Form_Click()
AutoRedraw = False
Cls
Print : Print : Print
Print "Pero esta línea desaparecerá después del doble clic"
End Sub
Sub Form_DblClick()
Cls
End Sub
Crear un nuevo formulario que tenga dos controles picture : uno con la propiedad ClipControls establecida a True y el otro a False. Cuando se ejecute este proyecto, se deberá arrastrar algún formulario hasta tapar parcialmente los círculos que aparecerán en los cuadros de imagen. Al retirarlo de nuevo, el color del círculo de Picture1 se cambia totalmente y, el de Picture2, cambia sólo en la parte que se expone nuevamente.
Sub Picture1_Paint()
Dim color As Long
Picture1.ScaleMode = 3
color = &HFFFFFF * Rnd
Picture1.FillStyle = 0
Picture1.FillColor = color
Picture1.Circle (43, 41), 30, color
End Sub
Sub Picture2_Paint()
Dim color As Long
Picture2.ScaleMode = 3
color = &HFFFFFF * Rnd
Picture2.FillStyle = 0
Picture2.FillColor = color
Picture2.Circle (43, 41), 30, color
End Sub
El método Refresh obliga a un refresco inmediato del formulario o del control. Este procedimiento se utiliza normalmente en el procedimiento Form_Resize para volver a presentar cualquier gráfico que se haya calculado en el procedimiento Paint. Para guardar los gráficos que se han dibujado en un formulario o caja de figuras se utiliza la orden :
SavePicture [NombreObjeto.] Image, NombreArchivo
ESCALAS DE LA PANTALLA.
La escala por omisión para los formularios y cajas de figuras viene medida en Twips. El tamaño por omisión de un formulario en una VGA normal es de 7.485 Twips de largo por 4.425 Twips de ancho. Veamos un ejemplo de coordenadas posibles en el formulario.
|
COORDENADAS |
POSICIÓN |
|
(0,0) |
Esquina superior izquierda |
|
(7485,0) |
Esquina superior derecha |
|
(0,4425) |
Esquina inferior izquierda |
|
(7485,4425) |
Esquina inferior derecha |
|
(3742,2212) |
Aproximadamente en el centro |
Para cambiar la unidad de medida se utiliza la propiedad ScaleMode.
EJEMPLO
Simularemos el movimiento de un botón superponiendo diferentes dibujos del mismo. Se necesita un botón de comando con sus valores por omisión (hacer doble clic sobre la herramienta)
Sub Command1_Click()
'Movimiento de un cuadrado simulando un paseo aleatorio
Dim x As Single, y As Single
Dim i As Integer
Randomize
Form1.ScaleMode = 3 'Unidad de medida Pixels
x = Form1.ScaleWidth / 2
y = Form1.ScaleHeight / 2
For i = 0 To 50
xmove = 3 * Rnd
ymove = 2 * Rnd
If Rnd < 0.5 Then
x = x + xmove
y = y + ymove
Else
x = x - xmove
y = y - ymove
End If
If x < 0 Or x > ScaleWidth Or y < 0 Or y > ScaleHeight Then
'No hacer nada
Else
Command1.Move x, y
End If
Next i
End Sub
ESCALAS PERSONALIZADAS.
El método Scale establece un nuevo sistema de coordenadas para los formularios y las cajas de figuras que se pueden usar con cualquiera de los métodos gráficos. Su sintaxis es :
[objeto.] Scale (x1, y1)-(x2, y2)
donde x1 e y1 se corresponden con ScaleLeft y ScaleTop y x2 e y2 con las sumas ScaleWidth + ScaleLeft y ScaleHeight + ScaleTop respectivamente. P.e.
Scale (-320,100)-(320,-100)
establece el nuevo sistema de coordenadas en el que las coordenadas de la esquina superior izquierda es (-320,100) y las de la esquina inferior derecha es (320,-100). La sintaxis del método Scale es :
Scale (Xizquierda, Yarriba)- (Xderecha, Yabajo)
Si se establece Scale sin coordenadas, se restablecerán las coordenadas por omisión.
Otra forma de establecer coordenadas personalizadas consiste en establecer las coordenadas de la esquina superior izquierda de la forma en la que se deben medir las escalas vertical y horizontal, utilizando las propiedades ScaleLeft, ScaleTop, ScaleWidth, y ScaleHeight.
EJEMPLO
|
(0,0) |
(1,0) |
ScaleLeft = 0 |
||
|
ScaleHeight = -1 |
||||
|
ScaleWidth = 1 |
||||
|
ScaleTop = 0 |
||||
|
(0,-1) |
(1,-1) |
|
(-40,40) |
(40,40) |
ScaleLeft = -40 |
||
|
ScaleHeight = -80 |
||||
|
l |
ScaleWidth = 80 |
|||
|
(0,0) |
ScaleTop = 40 |
|||
|
(-40,-40) |
(40,-40) |
Scale (-40,40)-(40,-40) |
Para dibujar líneas se utiliza el método Line, cuya sintaxis es :
Line (ColumnaInicial, FilaInicial)-(ColumnaFinal, FilaFinal), CódigoColor
Visual Basic recuerda el último punto referenciado y sus coordenadas están guardadas en las variables CurrentX y CurrentY, de forma que, para dibujar a continuación de este punto se utiliza :
Line -(ColumnaFinal, FilaFinal), CódigoColor
EJEMPLO
Programa que dibuja la ecuación y = x2 - 3x + 12 en el dominio -10 <= x <= 10
Function FdeX(ByVal x As Single) As Single
FdeX = (x ^ 2) - (x * 3) + 12
End Function
Sub Form_Paint()
Dim x As Single
'Configura la pantalla
Cls
Scale (-150, 150)-(150, -150) 'Sistema de coordenadas cartesianas estándar
'Dibujar los ejes
Line (-150, 0)-(150, 0)
Line (0, -150)-(0, 150)
CurrentX = -10
CurrentY = FdeX(-10)
For x = -10 To 10
Line -(x, FdeX(x)) 'Dibujar la línea desde la última posición conocida
Next x
End Sub
9. 2.- COLORES Y PIXELS.
COLORES.
Se puede utilizar la función RGB cuya sintaxis es:
RGB (CantidadRojo, CantidadVerde, CantidadAzul)
Siendo cada cantidad un entero entre 0 y 255 aunque también se podrá incluir al proyecto el archivo Constant.Txt y utilizar los códigos allí definidos.
Otra función que se puede utilizar es QBColor con la sintaxis :
QBColor (CódigoColor)
donde CódigoColor es un entero entre 0 y 15
EJEMPLO
Para dibujar los ejes del ejemplo anterior de color verde se modificarán las líneas siguientes:
Line (-150, 0)-(150, 0)
Line (0, -150)-(0, 150)
por estas otras
Line (-150, 0)-(150, 0), RGB(0,255,0)
Line (0, -150)-(0, 150), RGB(0,255,0)
CONTROL DE PIXELES.
La sintaxis para dibujar un pixel es :
PSet (Columna, Fila)[, Códigocolor]
Si se exceden los límites de la pantalla, se obtendrá un error de desbordamiento. Si se dibuja un punto fuera del formulario, Visual Basic guarda la posición si la propiedad AutoRedraw está a True. Si luego el formulario se maximiza, se dibujará el punto.
EJEMPLOS
Sub Form_Click()
Dim i As Integer
AutoRedraw = True
For i = 0 To 5000
PSet (3742, i) 'Dibujar una línea vertical
Next i
For i = 0 To 7485
PSet (i, 3500) 'Dibujar una línea horizontal
Next i
End Sub
Dim AlturaPixel As Single, AnchuraPixel As Single
Dim XPunto As Single, YPunto As Single
Sub Form_Load()
AutoRedraw = True
ScaleMode = 3 'Pixels
AlturaPixel = ScaleHeight
AnchuraPixel = ScaleWidth
XPunto = AnchuraPixel / 2
YPunto = AlturaPixel / 2
End Sub
Sub Form_Resize()
AlturaPixel = ScaleHeight
AnchuraPixel = ScaleWidth
End Sub
Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
Dim sino As Integer
Select Case KeyCode
Case Key_Left
If XPunto <= 0 Then
XPunto = 0
Else
XPunto = XPunto - 1
End If
Case Key_Right
If XPunto >= AnchuraPixel Then
XPunto = AnchuraPixel
Else
XPunto = XPunto + 1
End If
Case Key_Up
If YPunto <= 0 Then
YPunto = 0
Else
YPunto = YPunto - 1
End If
Case Key_Down
If YPunto >= AlturaPixel Then
YPunto = AlturaPixel
Else
YPunto = YPunto + 1
End If
Case Key_End
sino = MsgBox("¿Estás seguro de que quieres terminar", 4)
If sino = 6 Then End 'Clic en si
Case Else
Beep
End Select
PSet (XPunto, YPunto)
End Sub
Sub Form_Click()
Dim i As Integer, CodColor As Integer
Dim Columna As Single, Fila As Single
Randomize
Cls
Scale (-245, 134)-(245, -134)
For i = 1 To 100
Columna = 245 * Rnd
If Rnd < 0.5 Then Columna = -Columna
Fila = 134 * Rnd
If Rnd < 0.5 Then Fila = -Fila
CodColor = 15 * Rnd
Line (0, 0)-(Columna, Fila), QBColor(CodColor)
Next i
End Sub
En ocasiones resulta útil utilizar coordenadas relativas, en las que cada punto viene definido por cuánto de lejos está del último punto referenciado. P.e.
PSet (12,100)
PSet Step(50,10)
el nuevo punto será (62,110) o lo que es lo mismo, (12+50,100+10)
EJEMPLO
Crear un formulario con una caja de imágenes. Este proyecto dibujará en el formulario y en la caja, las curvas correspondientes a la función sen(x) y cos(x) para valores comprendidos entre 0 y 6.3. El sistema de coordenadas que se define permite mostrar valores de x entre 0 y 6.3 y, valores de y entre -1 y 1. Si se establece la propiedad AutoRedraw a False y, al ejecutar el propyecto, el formulario se minimza, al restauralo, las curvas no serán dibujadas.
Sub Curvas()
'Parámetros para el formulario
ScaleLeft = 0
ScaleTop = 1
ScaleWidth = 6.3
ScaleHeight = -2
DrawWidth = 2 'Grosor de la línea
FontSize = 18 'Tamaño de los caracteres
'Coordenadas del punto central del formulario
cx = ScaleWidth / 2 + ScaleLeft
cy = ScaleHeight / 2 + ScaleTop
Cls
msg = "Curvas"
'Coordenadas para escribir msg centrado
CurrentX = cx - TextWidth(msg) / 2
CurrentY = cy - TextHeight(msg) / 2
ForeColor = QBColor(2) 'Color verde
Print msg
ForeColor = QBColor(0) 'Color negro
'Parámetros para la imagen
Picture1.Scale (0, 1)-(6.3, -1)
Picture1.Cls
Picture1.CurrentX = cx - Picture1.TextWidth(msg) / 2
Picture1.CurrentY = cy - Picture1.TextHeight(msg) / 2
Picture1.ForeColor = QBColor(2)
Picture1.Print msg
Picture1.ForeColor = QBColor(0)
'Dibujar curvas
For x = 0 To 6.3 Step 0.05
yc = Cos(x)
ys = Sin(x)
PSet (x, yc): Picture1.PSet (x, yc) 'Coseno
PSet (x, ys): Picture1.PSet (x, ys) 'Seno
Next x
End Sub
Sub Form_Click()
Curvas
End Sub
ANCHURA Y ESTILO DE DIBUJO.
Para cambiar el grosor de los puntos o de las líneas, se utiliza la propiedad DrawWidth, cuya forma de empleo es :
Objeto.DrawWidth = Tamaño%
El ajuste de esta propiedad se mide en pixels.
Para cambiar el estilo de la línea, la propiedad a utilizar es DrawStyle, que se verá modificada cuando DrawWidth sea 1.
Para rellenar las cajas o círculos, se modificará las propiedades FillStyle y FillColor.
EJEMPLOS
Sub Form_Click()
WindowState = 2 'Maximizar
Dim i As Integer
For i = 1 To 10
DrawWidth = i
Line (0, i * ScaleHeight / 12)-(ScaleWidth - 15 * TextWidth("D"), i * ScaleHeight / 12)
Print "DrawWidth = ", i
Next i
End Sub
Dibujar cajas anidadas.
Sub Form_Click()
Dim i As Integer
Scale (0, 0)-(639, 199)
For i = 1 To 65 Step 5
Line (5 * i, i)-(639 - 5 * i, 199 - i), , B 'Dibujar una caja
Next i
End Sub
Demostración que no emplea líneas interiores.
Sub Form_Click()
WindowState = 2
DrawWidth = 10
Line (100, 100)-(ScaleWidth / 2, ScaleHeight / 2), , B
Line (ScaleWidth / 2, ScaleHeight / 2)-(ScaleWidth - 100, ScaleHeight - 100), , B
End Sub
Sub Form_Click()
WindowState = 2
DrawStyle = 6
DrawWidth = 10
Line (100, 100)-(ScaleWidth / 2, ScaleHeight / 2), , B
Line (ScaleWidth / 2, ScaleHeight / 2)-(ScaleWidth - 100, ScaleHeight - 100), , B
End Sub
Sub Form_Click()
Dim i As Integer
Scale (0, 0)-(639, 199)
For i = 1 To 65 Step 5
CodigoColor = QBColor(i Mod 16) 'Dibujar siguiendo el orden de los colores
Line (5 * i, i)-(639 - 5 * i, 199 - i), CodigoColor, BF
Next i
End Sub
Sub Form_Click()
Dim i As Integer
Scale (0, 0)-(25, 25)
For i = 0 To 7
FillStyle = i
Line (0, 3 * i)-(4, 3 * (i + 0.8)), , B
CurrentX = 4.1
CurrentY = 3 * i + 0.5
Print "Este está hecho con FillStyle #"; i
Next i
End Sub
Private Sub Form_Load()
AutoRedraw = -1
Print: Print: Print
Print Tab(12); "Artículo"; Tab(32); "Precio"
'Tab indica la posición donde se desea que comience la impresión de
‘una determinada expresión
Print Tab(12); "Garbanzos"; Tab(32); 500
Print Tab(12); "Lentejas"; Tab(32); 300
Print Tab(12); "Manzanas"; Tab(32); 400
Print Tab(12); "Plátanos"; Tab(32); 200
DrawWidth = 2
Line (700, 350)-(3650, 1950), , B
Line (700, 880)-(3650, 880)
End Sub
9.3.- CÍRCULOS, ELIPSES Y GRÁFICOS DE SECTORES.
CÍRCULOS.
Para describir un círculo se dará su centro y su radio y la función que dibuja los círculos es :
Circle (Centro), Radio, CódigoColor
EJEMPLO
Dibujar círculos anidados
Sub Form_Click()
Static CodColor As Integer
Dim i As Single
WindowState = 2
Scale (-1, 1)-(1, -1)
For i = 0.1 To 0.7 Step 0.5
CodColor = 15 * Rnd
Circle (0, 0), i, CodColor
Next i
End Sub
Un sector es una parte de un gráfico y un arco es el límite exterior de un sector. Para dibujar un sector o un arco hay que decirle a Visual Basic dónde tiene que empezar y dónde tiene que terminar, para lo que se tendrá que emplear los radianes como unidad de medida. Para transformar grados en radianes se multiplica por 180/p . Para dibujar un arco de circunferencia comenzando en el punto dado en radianes en AnguloInicial y terminando en AnguloFinal, se utilizará :
Circle (Xrad, Yrad), Radio, CódigoColor, AnguloInicial, AnguloFinal
Para obtener un sector se usan signos negativos.
EJEMPLO
Dibujaremos un sector y un arco.
Sub Form_Click()
Pi = 4 * Atn(1) 'Calcular el valor de Pi
Scale (-1, 1)-(1, -1)
Circle (-0.4, 0), 0.5, , -Pi / 4, -3 * Pi / 4 'Dibujar el sector
Circle (0.4, 0), 0.5, , Pi / 4, 3 * Pi / 4 'Dibujar el arco
End Sub
ELIPSES.
Para dibujar elipses se modificará el método Circle de la siguiente manera :
Circle [Paso] (Xcentro, Ycentro), radio,,,, aspecto
Si el parámetro aspecto es menor que 1, el radio se toma en la dirección de las columnas y la elipse tendrá su eje menor en dirección vertical.
EJEMPLOS
1.- Sub Form_Click()
Scale (-2, 2)-(2, -2)
Static I As Single
Cls
Circle (0, 0), 0.5, , , , I + 0.1
CurrentX = -2
CurrentY = 2
Print "Esta es la relación de aspecto "; Format$(I + 0.1, "#.#");
Print ". Haga clic para ver el siguiente tamaño de elipse"
I = I + 0.1
End Sub
2.- Dibujaremos un círculo, una elipse y un círculo con un sector desplazado.
Sub Form_Load()
Pi = 4 * Atn(1) ‘Definir el valor de Pi
C1 = RGB(0, 0, 255) 'Azul
C2 = RGB(0, 255, 0) 'Verde
C3 = RGB(255, 0, 0) 'Rojo
AutoRedraw = -1
ScaleMode = 3 ‘Pixels
Circle (60, 70), 30, C1 'Círculo
Circle (150, 70), 30, C2, , , 5 / 11 'Elipse
Circle (240, 70), 30, C3, -Pi / 2, -2 * Pi 'Sector
Circle Step(5, -5), 30, C1, -2 * Pi, -Pi / 2 'Sector
End Sub
3.- Rellenaremos el círculo, la elipse y el círculo con un sector desplazado del ejemplo anterior.
Sub Form_Load()
Pi = 4 * Atn(1) ‘Definir el valor de Pi
C1 = RGB(0, 0, 255) 'Azul
C2 = RGB(0, 255, 0) 'Verde
C3 = RGB(255, 0, 0) 'Rojo
AutoRedraw = -1
ScaleMode = 3 ‘Pixels
FillStyle = 0
FillColor = C1
Circle (60, 70), 30, C1 'Círculo
FillColor = C2
Circle (150, 70), 30, C2, , , 5 / 11 'Elipse
FillColor = C3: FillStyle = 4
Circle (240, 70), 30, C3, -Pi / 2, -2 * Pi 'Sector
FillColor = C1: FillStyle = 5
Circle Step(5, -5), 30, C1, -2 * Pi, -Pi / 2 'Sector
End Sub
4.- Simulación de una pelota rodando sobre una línea.
Sub Form_Click()
D = 100 ‘Radio de la pelota
BackColor = RGB(255, 255, 255) 'Blanco
ForeColor = RGB(0, 0, 255) 'Azul
CY = ScaleHeight / 2
'Línea sobre la que rueda la pelota
Line (0, CY + D)-(ScaleWidth, CY + D), QBColor(2)
FillStyle = 0 ‘Color sólido
FillColor = ForeColor ‘Color pelota
DrawMode = 10
'Animación
For I = 0 To ScaleWidth Step 30
Circle (I, CY), D ‘Dibujar la pelota
For retar = 0 To 1000
Next retar ‘Control de velocidad
Circle (I, CY), D ‘Borrar la pelota
Next I
End Sub
5.- Simulación de una pelota que rebota al chocar contra una barrera.
Sub Form_Click()
ScaleMode = 3 'Pixels
D = 5 'Radio de la pelota
BackColor = QBColor(15) 'Blanco
ForeColor = QBColor(1) 'Azul
CX = ScaleWidth / 4 * 3
CY = ScaleHeight / 2
'Barrera sobre la que rebota la pelota
Line (CX, 10)-(CX + 20, ScaleHeight - 10), QBColor(2), BF
FillStyle = 0 'Color sólido
FillColor = ForeColor 'Color pelota
DrawMode = 10
'Animación. Mover la pelota. Si choca, rebota
direccion = 1 '1=derecha, -1=izquierda
i = 3
Do While (i > 3 Or direccion = 1)
Circle (i, CY), D 'Dibujar la pelota
'Point da el color de la barrera cuando hay contacto. Devuelve el color RGB
‘ de un punto
If Point(i + 6, CY) <> BackColor Then direccion = -1
For retar = 0 To 300
Next retar 'Control velocidad
Circle (i, CY), D 'Borrar pelota
i = i + direccion
Loop
End Sub