General User Interface
Es una interfase grafica que te permite acceder y controlar
parámetros del código sin tener que ir directamente a
él. Al ser una interfase la podemos ubicar como un punto
intermedio entre el código y el usuario. SuperCollider provee
los elementos mas comunes de una interfase como son botones, controles,
perillas, campos numéricos y de texto, manipulacion de fuentes,
colores, menus y tiene además cierto potencial gráfico.
Las Clases que se usan para hacer GUIs tienen varios métodos que
nos sirven para definir su comportamiento y apariencia.
A continuación veremos las principales Clases para hacer uso la
GUI.
SCWindow(name, bounds, resizable, border, server, scroll)
Es una clase que crea una ventana sobre la cual podemos empezar a
construir nuestra interfase.
name - Nombre. Un string (entre comillas) o un symbol (antecedido por
una diagonal \). Este texto será el nombre que queremos que se
vea en nuestra ventana. (no confundir con la variable asignada al
nuestra instancia de SCWindow).
bounds - Límites. Las dimensiones de la ventana. Para esto
necesitamos la clase Rect que, a traves de cuatro argumentos, nos
permite definir la posición y el tamaño de la ventana.
resizable - Redimensionable. Un boleano (true / false) indicando si la
ventana se puede redimensionar (hacer mas grande o mas chica). Default
- true
border - Borde. Un boleano (true / false) indicando si la ventana
tendrá o no la pestaña superior que contiene el name y
los botones para cerrar y minimizar y maximizar. /*
¡¡¡CUIDADO!!! */ Si quitas el border no podras cerrar
la ventana a menos que lo hagas desde el código. Default - true.
server - Un argumento idiota. Solo sirve para proveer compatibilidad
con SwingOSC. O sea qu no le hagan caso. Default - agagaggu
scroll - Pergamino. Un boleano (true / false) indicando si la ventana
tendrá la capacidad de mostrar su contenido como pergamino en
caso de que este exceda las dimensiones de la ventana. Si damos true a
este argumento el argumento resizable queda anulado. Default - false.
Ejemplo 1
a=SCWindow("la ventanita del amor", Rect(100,100,400,300)).front
Para empezar asignamos la SCWindow a una variable para poder referirnos
a la instancia que estamos creando. Nuestra ventana se llama "la
ventanita del amor". Sus dimensiones estan dadas con la clase Rect que,
a traves de cuatro argumentos, nos permite definir la posición y
el tamaño de la ventana (ver ejamplo 2). Los demás
argumentos los dejamos con los valores predeterminados (default)
Ejemplo 2
Rect(posición en x, posición en y, tamaño en x,
tamaño en y)
Las cordenadas en la pantalla tienen su origen en la esquina inferior
izquierda. (O sea que ahi es el (0,0)). Por el contrario, las
cordenadas en la SCWindow tienen su origen en la esquina superior
izquierda. En el ejemplo 1 tenemos una ventana que tiene su borde
izquierdo a 100 pixeles de distancia del marco izquierdo de la
pantalla, su borde inferior esta a 100 pixeles del marco inferior de la
pantalla y tiene de ancho 400 pixeles y de alto 300 pixeles.
SCButton(parent, bounds)
Es una clase que crea un botón dentro de nuestra ventana.
parent - Ventana en la que queremos que se cree el botón. Nos
referimos a la ventana con la variable que le hallamos asignado.
bounds - Dimensiones del botón. Se necesita la clase Rect.
Existen algunos métodos básicos para configurar nuestro
SCButton.
states - Sirve para detrminar cuántos estados tiene nuestro
botón: 1 estado, 2 estados, 5 estados... cuántos estados
quieres? Al mismo tiempo determina el texto, el color del texto y el
color del fondo para cada estado. Los cambios de estado se originan al
apretar el botón.
action - Es una función que determina la acción que se
realizará al cambiar a un estado específico.
Ejemplo 3
(
a=SCWindow("la ventanita del amor", Rect(100,100,400,300)).front;
b=SCButton(a, Rect(100,10,150,100));
b.states=[["nO", Color.white, Color.black]];
b.action={|val| val.value.postln; "tengo miedo".postln};
)
En el ejemplo 3 creamos nuevamente una instancia a de SCWindow y una
instancia b de SCButton. Colocamos el botón en la ventana a. A
través de la clase Rect colocamos el botón a 100 pixeles
hacia la derecha y a 10 pixeles hacia abajo. Le damos 150 pixeles de
ancho y 100 de alto. Después, mediante el método states,
determinamos los estados que va a tener nuestro boton. Para esto
hacemos un array dentro del cual colocamos arrays para cada estado.
Cada array de estado tiene tres elementos :
1 - el texto ente comillas,
2 - el color del texto y
3 - el color del fondo.
Los coloes los designamos mediante la clase Color. Es recomendable ir
al archivo de ayuda para ver cómo funciona esta clase. En el
ejemplo 3 tenemos un estado que despliega el texto "nO" de color blanco
sobre negro. El siguiente método es action. Toda la accion del
botón va dentro de llaves {}. Dentro de las llaves primero
creamos un argumento que puede tener el nombre que queramos. En este
caso usamos val. Se puede crear con pipes |val| o escribiendo arg val;
Después podemos escribir las acciones que queramos separadas por
;
Ejemplo 4
(
a=SCWindow("la ventanita del amor", Rect(100,100,400,300)).front;
b=SCButton(a, Rect(100,100,150,100));
b.states=[["nO", Color.white, Color.black], ["Si", Color.black,
Color.red]];
b.action={|val| if(val.value==0, {"tengo hambre".postln}, {"se me
enterro una yema".postln})};
)
En el Ejemplo 4 tenemos 2 estados en el método states. Por eso
tenemos un array cuyos elementos son dos arrays. En el método
action hemos incluido un if que evalúa al argumnto val.
Necesitamos usar el método value (val.value) para poder
evaluarlo. En el ejemplo hemos decidio que si val es 0 entonces se
escribe "tengo hambre" y si no es 0 escribe "se me enterro una yema".
Los estados se empiezan a contar a partir del 0. Asi que en este caso
tenemos el estado 0 y el estado 1.
Ejemplo 4.5
(
a=SCWindow("la ventanita del amor", Rect(100,100,400,300)).front;
b=SCButton(a, Rect(100,100,150,100));
b.font=Font("BrushScriptMT", 70);
b.states=[["nO", Color.white, Color.black], ["Si", Color.black,
Color.red]];
b.action={|val| if(val.value==0, {"tengo hambre".postln}, {"se me
enterro una yema".postln})};
)
En el ejemplo 4.5 agregamos el metodo Font para cambier las
caracteristicas de la letra. Ver el archivo de ayuda de Font y poner
especial atencion en el segundo ejemplo.
Ejemplo 5
(
a=SCWindow("la ventanita del amor", Rect(100,100,400,300)).front;
b=SCButton(a, Rect(100,100,150,100));
b.states=[["nO", Color.white, Color.black], ["Si", Color.black,
Color.red]];
b.action={|val|
if(val.value==0, {
{Pulse.ar(XLine.kr(60,2000,0.125, doneAction:2),0.5,0.5)}.play
},
{
{Saw.ar(SinOsc.kr(10,0,100,300))*Line.kr(1,0,0.5,doneAction:2)}.play
}
)
};
)
En el ejemplo 5 asignamos Synths a las acciones del boton de igual
manera que lo hicimos con los textos en el ejemplo 4. También
podemos encender Tdefs y detenerlos como se muestra en el ejemplo 6.
Ejemplo 6
(
Tdef(\escrupuloso, {var cuenta=0;
inf.do{
switch(cuenta%4,0,{{Pulse.ar(XLine.kr(60,2000,0.125,
doneAction:2),0.5,0.5)}.play},
1,{{Saw.ar(SinOsc.kr(10,0,100,300))*Line.kr(1,0,0.25,doneAction:2)}.play},
2,{{Pulse.ar(XLine.kr(60,400,0.125, doneAction:2),0.5,0.5)}.play},
3,{{Saw.ar(SinOsc.kr(10,0,100,rrand(300,1000)))*Line.kr(1,0,0.25,doneAction:2)}.play}
);
cuenta=cuenta+1;
0.2.wait;
}
}).quant_(0);
)
(
a=SCWindow("la ventanita del amor", Rect(100,100,400,300)).front;
b=SCButton(a, Rect(100,100,150,100));
b.states=[["nO", Color.white, Color.black], ["Si", Color.black,
Color.red]];
b.action={|val|
if(val.value==1, {
Tdef(\escrupuloso).play;
"El escrupuloso anda".postln;
},
{
Tdef(\escrupuloso).stop;
"El escrupuloso no va".postln;
}
)
};
)
Agregemos ahora otro boton para darle mas funcionalidad a la GUI. En el
ejemplo 7 ponemos un boton que nos dispare un Synth.
Ejemplo 7
(
a=SCWindow("la ventanita del amor", Rect(100,100,400,300)).front;
b=SCButton(a, Rect(50,100,150,100));
b.states=[["nO", Color.white, Color.black], ["Si", Color.black,
Color.red]];
b.action={|val|
if(val.value==1, {
Tdef(\escrupuloso).play;
"El escrupuloso anda".postln;
},
{
Tdef(\escrupuloso).stop;
"El escrupuloso no va".postln;
}
)
};
c=SCButton(a, Rect(210,100,150,100));
c.states=[["WepA!!", Color.white, Color.black]];
c.action={{RHPF.ar(Saw.ar(30),rrand(200,1000),0.1,2.5)*Line.kr(1,0,0.41,doneAction:2)}.play};
)
Observar como en el ejemplo 7 al nuevo boton se le asigno una variable
propia, en este caso c, y la posición dada por el Rect tiene
coordenadas diferentes para que no se encime con el boton b.
Para cambiar el propiedades de un objeto en una ventana desde afuera
usamos el metodo .valueAction como en el ejemplo 8
Ejemplo 8
(
a=SCWindow("la ventanita del amor", Rect(100,100,400,300)).front;
b=SCButton(a, Rect(100,10,150,100));
b.states=[["nO", Color.white, Color.black],["bueno", Color.red,
Color.white]];
b.action={|val| val.value.postln; "tengo miedo".postln};
)
b.valueAction=1
b.valueAction=0
Cabe mencionar que si queremos cambiar estas propiedades desde un Tdef
de manera automatica necesitamos poner entre llaves {} la linea que
realizara esta accion
Esto no sirve
(
Tdef(\vaya, {
inf.do{|i|
b.valueAction=i%2;
0.5.wait;
}
})
)
Tdef(\vaya).play
Pero esto si
(
Tdef(\vaya, {
inf.do{|i|
{b.valueAction=i%2}.defer;
0.5.wait;
}
})
)
Tdef(\vaya).play
Tdef(\vaya).stop