SimpleUI para Processing
Una única librería para construir interfaces gráficas en proyectos de Processing Desktop y Processing for Android, acompañada de un calendario y del motor de tareas SimpleCore.
Una API reconocible
Botones, etiquetas, listas, tablas, campos de texto, calendarios y vistas comparten una estructura y un sistema de eventos coherentes.
Sketches limpios
La librería registra automáticamente los eventos de ratón, toque y teclado. El sketch conserva únicamente su lógica y el dibujo.
Dos plataformas
El código se mantiene casi idéntico. Solo cambia el import: simpleui.desktop.* o simpleui.android.*.
Tareas independientes
simplecore.* proporciona tareas con ciclo de vida, prioridad, señales y representación gráfica opcional.
Modelo mental
- Se inicializa
SimpleUIcon el sketch. - Se crean controles y se añaden al registro global.
- Un único
UIEventHandlerrecibe las acciones del usuario. updateAndDrawUI()actualiza y dibuja la interfaz en cada fotograma.
import simpleui.desktop.*; // En Android: import simpleui.android.*;
UIButton boton;
void setup() {
size(640, 360);
SimpleUI.initUI(this, "SansSerif", 18);
boton = new UIButton("saludar", 30, 40, 180, 48, "Saludar", 18);
SimpleUI.addUIElement(boton);
}
void draw() {
background(SimpleUI.currentTheme.backgroundColor);
SimpleUI.updateAndDrawUI();
}Instalación y arranque
Instalar
Copia la carpeta completa SimpleUI dentro de la carpeta libraries del sketchbook de Processing. El archivo cargado por Processing es SimpleUI/library/SimpleUI.jar. Reinicia el IDE después de instalar o actualizar la librería.
Elegir el import
// Processing Desktop
import simpleui.desktop.*;
// Processing for Android
import simpleui.android.*;
// SimpleCore es común a las dos plataformas
import simplecore.*;Esqueleto mínimo
import simpleui.desktop.*;
void settings() {
size(800, 600);
}
void setup() {
SimpleUI.initUI(this, "SansSerif", 18);
SimpleUI.setMode(800, 600);
}
void draw() {
background(SimpleUI.currentTheme.backgroundColor);
SimpleUI.updateAndDrawUI();
}setMode(anchoDiseño, altoDiseño) define la resolución virtual completa. SimpleUI calcula la escala y transforma tanto el dibujo como la entrada del ratón o la pantalla táctil.Orden de dibujo
updateAndDrawUI() debe ejecutarse después del fondo y del contenido que tenga que quedar detrás de la interfaz. Si necesitas separar ambas fases, utiliza updateUI() y drawUI().
Eventos automáticos
initUI() instala un puente de eventos mediante el ciclo de vida de Processing. No es necesario declarar mousePressed(), mouseDragged(), mouseReleased(), keyPressed() ni keyTyped() en el sketch.
Recibir eventos
SimpleUI.setUIEventHandler(new UIEventHandler() {
public void onUIEvent(UIElement element, String action, Object data) {
println(element.id + " → " + action + " → " + data);
if (element.id.equals("guardar") && action.equals("clicked")) {
guardarDatos();
}
}
});| Control | Acción | Contenido de data |
|---|---|---|
| UIButton | clicked | null |
| UICheckbox / UISwitch | changed | boolean |
| UIDropdown | changed | opción seleccionada |
| UISlider | changed | float |
| UIList | itemSelected | texto seleccionado |
| UITable | rowSelected | String[] |
| UITabs | tabChanged | etiqueta seleccionada |
| Campos | changed, submitted | texto o número |
| UICalendar | dateSelected | UICalendarSelection |
Control manual y teclado Android
setAutomaticEventHandling(false)Desactiva el puente automático si una integración avanzada necesita reenviar los eventos manualmente.
setKeyEventInterceptor(interceptor)Permite consumir una tecla antes de que llegue a SimpleUI; es útil para la tecla Atrás de Android.
detach()Desregistra el puente y libera la referencia al sketch. Normalmente se ejecuta automáticamente en dispose.
Desktop y Android
Las dos implementaciones viven en el mismo JAR, pero en paquetes separados para evitar dependencias Android al compilar un sketch Desktop.
| Capacidad | Desktop | Android |
|---|---|---|
| Controles, eventos, vistas y calendario | Sí | Sí |
| SimpleCore | Sí | Sí |
| Teclado nativo y ajuste al teclado virtual | Teclado Processing | Sí |
UISignalMeter | Sí | Sí |
UIRect | Sí | Sí |
Footer y recibo de lectura en chatArea | Sí | Sí |
Contrato común desde 0.5.0
- Controles y modelos: todas las clases ofrecen los mismos constructores y métodos públicos en los dos paquetes.
- Resolución virtual:
setMode(),UIScaleModey las conversiones de coordenadas funcionan igual en Desktop y Android. - UISwitch: ofrece una selección booleana compacta y emite
changed. - UIDropdown: emite
changed. - UISlider: emite
changeddurante el movimiento yreleasedal terminar. - Modales: admiten tanto
actionIdcon handler como callbacksRunnable. - chatArea: admite footer y recibo de lectura en ambas plataformas.
SimpleUI
SimpleUI mantiene el host de Processing, la colección de controles, el tema, la escala, los estados de interacción y el receptor global de eventos.
API de uso habitual
initUI(this, fuente, tamaño)Conecta el sketch, crea la fuente, carga el tema y registra los eventos.
setMode(ancho, alto)Define una resolución virtual y usa el modo proporcional FIT.
setMode(ancho, alto, UIScaleMode)Elige entre FIT, FILL y RESPONSIVE.
getLogicalWidth() / getLogicalHeight()Devuelve el área disponible en coordenadas de diseño.
addUIElement(elemento)Añade un control al registro global y al orden de dibujo.
getUIElement(id)Busca un control por identificador; devuelve null si no existe.
removeUIElement(id)Retira el control indicado y devuelve si fue encontrado.
clearUIElements()Elimina todos los controles y limpia estados de interacción.
updateAndDrawUI()Sincroniza, actualiza gestos y dibuja controles, menús, inputs y modales.
setUIEventHandler(handler)Registra el receptor global de eventos.
setTheme(UIColorTheme.DARK)Cambia entre tema oscuro y claro.
setUIAlpha(alpha)Define opacidad global entre 0 y 255.
enableAllElements() / disableAllElements()Activa o desactiva todos los controles registrados.
getUIToday()Devuelve la fecha local actual como UIDate.
Estado público útil
currentTheme, uiScale, scaleMode, designWidth, designHeight, logicalWidth, logicalHeight, viewportOffsetX, viewportOffsetY, modeConfigured, uiElements, activeDropdown, activeTextField y activeUIModal permiten inspección avanzada. Para enseñanza inicial es preferible usar los métodos de alto nivel.
SimpleUI.LIBRARY_AUTHOR devuelve "Luis lopez martinez" y SimpleUI.LIBRARY_LICENSE devuelve "MIT". Las mismas constantes están disponibles en simplecore.Core.
handleUI…() son públicas por la forma en que se genera la librería, pero pertenecen a la infraestructura. No suelen llamarse desde un sketch.Resolución virtual y escala
Diseña una sola vez con una resolución lógica —por ejemplo 1280 × 720— y deja que SimpleUI adapte dibujo, controles, modales y entrada a la ventana o pantalla real.
SimpleUI.initUI(this, "SansSerif", 18);
SimpleUI.setMode(1280, 720, UIScaleMode.RESPONSIVE);
void draw() {
background(SimpleUI.currentTheme.backgroundColor);
SimpleUI.updateAndDrawUI();
}Modos disponibles
| Modo | Comportamiento | Uso recomendado |
|---|---|---|
FIT | Conserva la proporción, muestra toda la resolución de diseño y centra el contenido. Puede dejar bandas libres. | Interfaces de tamaño fijo que nunca deben recortarse. |
FILL | Conserva la proporción y llena toda la superficie. El exceso queda fuera del viewport. | Fondos o experiencias donde se admite recorte. |
RESPONSIVE | Usa la escala de FIT, pero expone el espacio sobrante como coordenadas lógicas adicionales. | Ventanas redimensionables y distintas relaciones de aspecto en Android. |
setMode(1280, 720) equivale a setMode(1280, 720, UIScaleMode.FIT).API del viewport
getLogicalWidth() / getLogicalHeight()Dimensiones utilizables por el layout. En RESPONSIVE pueden superar la resolución base.
screenToDesignX(x) / screenToDesignY(y)Convierte una coordenada física de la ventana a coordenadas lógicas.
designToScreenX(x) / designToScreenY(y)Convierte una coordenada lógica a píxeles físicos.
updateViewport()Recalcula manualmente escala y viewport. La actualización normal ya lo hace automáticamente.
Estado resuelto del viewport
| Campo | Contenido |
|---|---|
designWidth / designHeight | Resolución virtual solicitada mediante setMode(). |
logicalWidth / logicalHeight | Área lógica resuelta. Para código de aplicación se recomiendan los getters equivalentes. |
uiScale | Factor aplicado a dibujo e interacción. |
viewportOffsetX / viewportOffsetY | Desplazamiento físico, en píxeles de pantalla, usado para centrar FIT o recortar FILL. |
scaleMode | Modo UIScaleMode actualmente activo. |
modeConfigured | Indica si ya se ha definido una resolución virtual. |
setMode() y consulta las dimensiones mediante sus getters.Layout adaptable
SimpleUI escala automáticamente cada control, pero no decide cómo repartir el espacio adicional de RESPONSIVE. Cuando cambien getLogicalWidth() o getLogicalHeight(), usa setPosition() y setSize() para ampliar tablas, paneles o áreas gráficas.
uiScale: los modos centrados también tienen desplazamiento de viewport.UIElement
UIElement(String id, int x, int y, int width, int height)Es la base de todos los controles. Define posición, dimensiones, identificador, visibilidad, activación y anclaje.
setPosition(x, y)Mueve el control.
setSize(w, h)Cambia sus dimensiones.
setVisible(boolean)Controla si se dibuja y participa en la interfaz.
setEnabled(boolean)Controla si acepta interacción.
setAnchored(boolean)Marca un elemento fijo frente al desplazamiento global, especialmente útil en Android.
containsPoint(px, py)Comprueba si unas coordenadas están dentro del rectángulo.
hasScrollableOverflow()Indica si el control puede consumir un gesto vertical interno.
x, y, width, height, id, isVisible e isEnabled son públicos. Para código más legible, usa sus setters cuando existan.Temas y configuración
UIColorTheme contiene los valores DARK y LIGHT. UIConfig representa los seis colores resueltos del tema.
SimpleUI.setTheme(UIColorTheme.DARK);
background(SimpleUI.currentTheme.backgroundColor);
int acento = SimpleUI.currentTheme.accentColor;
int texto = SimpleUI.currentTheme.textColor;| Campo de UIConfig | Uso |
|---|---|
backgroundColor | Fondo general del sketch. |
surfaceColor | Superficies de controles y paneles. |
textColor | Texto principal. |
accentColor | Selección, progreso y énfasis. |
borderColor | Bordes y separadores. |
placeholderColor | Texto orientativo de inputs. |
Varios controles proporcionan setColors(), setTextColor() o setBorderColor() para sobrescribir localmente el tema.
UIButton y UIImageButton
UIButton(id, x, y, w, h, label, fontSize)
UIImageButton(id, x, y, w, h, PImage imagen)
UIImageButton(id, x, y, w, h, PImage imagen, imageW, imageH)UIButton representa una acción textual. UIImageButton hereda su comportamiento y reemplaza la presentación por una imagen.
setLabel(texto)Cambia el texto del botón.
setColors(relleno, borde, texto)Activa colores personalizados.
setPressedVisual(boolean)Fuerza el estado visual presionado.
setImage(PImage)Cambia la imagen de UIImageButton.
setImageSize(w, h)Define el tamaño dibujado de la imagen.
Evento clicked, con data == null.
UIButton guardar = new UIButton("guardar", 30, 30, 160, 46, "Guardar", 18);
SimpleUI.addUIElement(guardar);
// En onUIEvent:
if (element == guardar && action.equals("clicked")) {
println("Datos guardados");
}UILabel y UIIndicator
UILabel(id, x, y, w, h, texto, fontSize)
UIIndicator(id, x, y, size)UILabel muestra texto no interactivo; UIIndicator dibuja un testigo circular de estado.
label.setText(texto)Actualiza el contenido.
label.setTextAlignment(horizontal, vertical)Usa constantes Processing como LEFT, CENTER, TOP.
indicator.setIndicatorColor(color)Cambia el color del testigo.
indicator.setBorderColor(color)Personaliza el borde; clearBorderColor() recupera el tema.
UILabel estado = new UILabel("estado", 60, 30, 260, 30, "Conectado", 18);
UIIndicator led = new UIIndicator("led", 30, 33, 20);
led.setIndicatorColor(color(30, 190, 100));
SimpleUI.addUIElement(estado);
SimpleUI.addUIElement(led);UICheckbox y UISwitch
UICheckbox(id, x, y, size, label, fontSize)
UISwitch(id, x, y, w, h, label, initialValue, fontSize)Ambos controles representan un valor booleano. UICheckbox usa una casilla tradicional; UISwitch ofrece un interruptor compacto con pista, cursor y etiqueta, integrado con escala, temas y eventos.
isChecked()Consulta el estado actual.
setChecked(boolean)Modifica el estado desde el programa sin emitir un evento.
setLabel(texto)Cambia la etiqueta mostrada junto al interruptor.
toggle()Invierte el estado y emite changed. No actúa si el control está deshabilitado.
Evento Los dos emiten changed; data contiene el nuevo boolean.
UICheckbox sonido = new UICheckbox("sonido", 30, 40, 24, "Activar sonido", 17);
sonido.setChecked(true);
SimpleUI.addUIElement(sonido);
UISwitch ordenar = new UISwitch(
"ordenar", 30, 85, 250, 38,
"Ordenar por intensidad", false, 16
);
SimpleUI.addUIElement(ordenar);
// En onUIEvent:
if (element == sonido && action.equals("changed")) {
boolean activo = (Boolean)data;
}
if (element == ordenar && action.equals("changed")) {
println((Boolean)data ? "Orden RSSI" : "Orden topológico");
}UISlider y UIProgressBar
UISlider(id, x, y, w, h, min, max, initialValue, fontSize)
UIProgressBar(id, x, y, w, h)slider.getValue() / setValue(v)Consulta o cambia el valor, limitado al rango.
progress.setProgress(v)Define progreso entre 0 y 1.
progress.getProgress()Consulta el progreso.
progress.setColors(track, fill)Personaliza pista y relleno.
UISlider emite changed con un float durante el movimiento y released al finalizar.
UISlider volumen = new UISlider("volumen", 30, 50, 280, 34, 0, 100, 50, 16);
UIProgressBar nivel = new UIProgressBar("nivel", 30, 105, 280, 18);
SimpleUI.addUIElement(volumen);
SimpleUI.addUIElement(nivel);
// En onUIEvent:
if (element == volumen && action.equals("changed")) {
nivel.setProgress(((Float)data) / 100.0);
}UIDropdown y UITabs
UIDropdown(id, x, y, w, h, String[] options, fontSize)
UITabs(id, x, y, w, h, String[] tabs, fontSize)UIDropdown
getSelectedValue()Devuelve la opción actual.
getSelectedIndex() / setSelectedIndex(i)Consulta o selecciona por índice.
setOptions(String[])Reemplaza todas las opciones.
isOpen() / setOpen(boolean)Consulta o cambia la apertura.
Evento changed con el texto elegido.
UITabs
getSelectedIndex()Índice de pestaña activa.
getSelectedLabel()Etiqueta activa.
setSelectedIndex(i)Selecciona una pestaña.
Evento tabChanged con la etiqueta elegida.
String[] modos = { "Básico", "Avanzado", "Experto" };
UIDropdown selector = new UIDropdown("modo", 30, 40, 220, 44, modos, 17);
UITabs tabs = new UITabs("secciones", 30, 110, 360, 42,
new String[]{ "Inicio", "Datos", "Ajustes" }, 16);
SimpleUI.addUIElement(selector);
SimpleUI.addUIElement(tabs);UIList y UITable
UIList(id, x, y, w, h, fontSize)
UITable(id, x, y, w, h, String[] headers, float[] columnWidths, fontSize)UIList
addItem(texto)Añade una entrada.
getItemCount()Número de entradas.
getSelectedIndex()Índice seleccionado; -1 si no hay selección.
clearItems() / scrollToBottom()Limpia o desplaza al final.
setTitle(texto)Muestra una cabecera.
Evento itemSelected con el texto.
UITable
addRow(String[])Añade una fila; debe corresponder con las columnas.
clearRows() / getRowCount()Limpia o cuenta las filas.
scrollToBottom()Muestra las últimas filas.
hasScrollableOverflow()Indica si existen más filas que espacio visible.
minimumScroll()Devuelve el límite inferior del desplazamiento interno.
Evento rowSelected con la fila como String[].
Cuando hay desbordamiento, la tabla muestra automáticamente un rail vertical y un cursor proporcional: cuanto mayor sea la parte visible del contenido, mayor será el cursor. Puede desplazarse con rueda, arrastre del contenido, arrastre del cursor o clic sobre el rail.
UITable alumnos = new UITable("alumnos", 30, 40, 520, 260,
new String[]{ "Nombre", "Curso", "Nota" },
new float[]{ .45, .30, .25 }, 16);
alumnos.addRow(new String[]{ "Ada", "Processing", "9.5" });
alumnos.addRow(new String[]{ "Alan", "Java", "8.7" });
SimpleUI.addUIElement(alumnos);UITextField y UITextArea
UITextField(id, x, y, w, h, placeholder, fontSize)
UITextArea(id, x, y, w, h, placeholder, fontSize)UITextField introduce una sola línea. UITextArea admite varias líneas, ajuste de texto y desplazamiento interno.
getText() / setText(texto)Lee o escribe el contenido.
setMaxLen(n)Limita el número de caracteres.
setUppercase(boolean)Convierte la entrada a mayúsculas.
setFocused(boolean) / isFocused()Controla el foco.
submitAndCloseKeyboard()Confirma y cierra el teclado.
setTextColor() / setBorderColor()Personaliza los colores; los métodos clear…() recuperan el tema.
area.scrollToBottom()Desplaza el área multilínea hasta el final.
Eventos changed durante la edición y submitted al confirmar; ambos entregan el texto.
UITextField nombre = new UITextField("nombre", 30, 40, 300, 44, "Tu nombre", 17);
nombre.setMaxLen(40);
UITextArea notas = new UITextArea("notas", 30, 105, 420, 150, "Observaciones", 16);
SimpleUI.addUIElement(nombre);
SimpleUI.addUIElement(notas);UINumberField
UINumberField(id, x, y, w, h, placeholder, fontSize)setAllowDecimal(boolean)Permite o bloquea decimales.
setAllowNegative(boolean)Permite o bloquea signo negativo.
setRange(min, max) / clearRange()Define o elimina límites.
isValidNumber()Comprueba que el texto es un número final válido.
getFloatValue() / getIntValue()Devuelve el valor o null si no puede convertirse.
getText() / setText()Accede a la representación textual.
Eventos changed entrega texto; submitted entrega Float o null.
UINumberField nota = new UINumberField("nota", 30, 40, 180, 44, "0 a 10", 17);
nota.setAllowDecimal(true);
nota.setAllowNegative(false);
nota.setRange(0, 10);
SimpleUI.addUIElement(nota);UIPanel
UIPanel(id, x, y, w, h)Superficie visual para agrupar controles. No contiene automáticamente otros elementos: el programador coloca los controles sobre sus coordenadas y debe añadir primero el panel para que quede detrás.
setTitle(texto, fontSize)Añade título.
clearTitle()Oculta el título.
setColors(fill, border, title)Define colores personalizados.
clearCustomColors()Recupera los colores del tema.
UIPanel panel = new UIPanel("datos", 20, 20, 420, 180);
panel.setTitle("Datos del alumno", 18);
SimpleUI.addUIElement(panel); // Primero: queda detrás
SimpleUI.addUIElement(new UITextField("nombre", 40, 70, 300, 42, "Nombre", 16));chatArea
chatArea(id, x, y, w, h)Área desplazable que presenta mensajes como burbujas a izquierda o derecha. El nombre público de la clase comienza en minúscula por compatibilidad con el código original.
addMessage(side, text)Añade un mensaje. Usa lados coherentes en todo el proyecto, por ejemplo 0 izquierda y 1 derecha.
clearMessages()Elimina el historial.
scrollToBottom()Muestra el mensaje más reciente.
setPanelColor() / setLeftCardColor() / setRightCardColor()Personaliza panel y burbujas.
addMessage(side, text, footer, readReceipt). ChatAreaMessage almacena side, text, footer y readReceipt.chatArea chat = new chatArea("chat", 20, 30, 440, 300);
chat.addMessage(0, "¿Preparado para empezar?");
chat.addMessage(1, "Sí, vamos allá.");
chat.scrollToBottom();
SimpleUI.addUIElement(chat);UISignalMeter
UISignalMeter(id, x, y, w, h, label)Representa intensidad de señal a partir de RSSI en dBm y la traduce a segmentos y etiqueta de S-meter.
setLabel(texto)Cambia la etiqueta.
setRssi(dbm)Actualiza la medida.
setPending(boolean)Muestra estado pendiente.
smeterLabelFromRssi()Obtiene la etiqueta S correspondiente.
smeterSegmentsFromRssi()Obtiene el número de segmentos.
UISignalMeter señal = new UISignalMeter("rssi", 30, 30, 300, 70, "LoRa");
señal.setRssi(-92);
SimpleUI.addUIElement(señal);UIView y UIViewManager
Una UIView agrupa controles que deben aparecer y desaparecer juntos. UIViewManager prepara vistas, cambia la vista activa y enruta sus eventos.
Ciclo de vida de una vista
initialize()Obligatorio. Crea y registra controles una sola vez.
onShow()Se ejecuta al mostrarse.
onHide()Se ejecuta al ocultarse.
onDestroy()Libera recursos propios.
addControl(elemento)Asocia un control a la vista.
UIViewManager
prepare(view)Inicializa sin mostrar.
show(view)Oculta la actual y muestra la nueva.
hide(view) / destroy(view)Oculta o destruye.
getActiveView()Devuelve la vista activa.
routeEvent(element, action, data)Entrega un evento a la vista propietaria.
UIViewManager paginas = new UIViewManager("principal");
class InicioView extends UIView {
InicioView() { super("inicio", paginas); }
public void initialize() {
addControl(new UIButton("continuar", 30, 40, 180, 44, "Continuar", 17));
}
}
InicioView inicio = new InicioView();
paginas.show(inicio);Modales
Alertas rápidas
showAlertModal(título, mensaje, botón)Muestra un aviso con una acción de cierre.
hideAlertModal()Cierra el aviso.
isAlertModalVisible() / isAnyModalVisible()Consulta el estado modal.
SimpleUI.showAlertModal("Información", "Los cambios se han guardado.", "Aceptar");Confirmación
Ambas plataformas permiten usar showConfirmModal(título, mensaje, aceptar, cancelar, actionId) con setModalResultHandler(), o la variante con dos callbacks Runnable.
SimpleUI.showConfirmModal("Borrar", "¿Eliminar el registro?", "Sí", "No",
new Runnable() { public void run() { borrar(); } },
new Runnable() { public void run() { println("Cancelado"); } }
);UIModal personalizado
Subclasifica UIModal, implementa initialize(), añade controles con addControl() y usa show()/hide(). Los hooks onShow() y onHide() permiten reaccionar al ciclo de vida.
UICalendar
UICalendar(id, x, y, w, h)
UICalendar(id, x, y, w, h, UIDate initialDate)Navegación y selección
showPreviousMonth() / showNextMonth()Navega un mes.
showPreviousYear() / showNextYear()Navega un año.
showToday()Vuelve al mes actual.
setDisplayedMonth(year, month)Muestra un mes concreto.
selectDate() / setSelectedDate()Selecciona fecha y emite evento / fija la selección.
getSelectedDate() / clearSelection()Consulta o limpia la selección.
Eventos de agenda
addEvent(id, fecha, título)Añade un evento de un día.
addEvent(id, inicio, fin, título)Añade un intervalo con UIDate o UIDateTime.
getEvent(id) / hasEvent(id) / removeEvent(id)Gestiona por identificador.
getEventsForDate(fecha)Obtiene una lista segura para esa fecha.
getEventsForDisplayedMonth()Obtiene los eventos visibles.
clearEvents()Vacía la agenda.
Eventos dateSelected → UICalendarSelection; selectionCleared; monthChanged, yearChanged y viewChanged → UIDate.
UICalendar calendario = new UICalendar("agenda", 30, 30, 430, 350);
UIDate hoy = SimpleUI.getUIToday();
calendario.addEvent("clase", hoy, "Clase de Processing")
.setColor(color(37, 99, 235))
.setData("Aula 2");
SimpleUI.addUIElement(calendario);
// En onUIEvent:
if (element == calendario && action.equals("dateSelected")) {
UICalendarSelection seleccion = (UICalendarSelection)data;
println(seleccion.date + " · " + seleccion.events.size() + " eventos");
}UICalendarEvent
Expone getId(), getTitle(), getStart(), getEnd(), getColor(), getData() e isVisible(). Sus setters encadenables son setTitle(), setColor(), setData(), setVisible() y setInterval(). También ofrece occursOn(), hasStarted(), hasFinished(), isActiveAt() y getDuration().
Fechas y tiempo
UIDate
UIDate(year, month, day)
UIDate(otraFecha)Fecha inmutable con campos year, month y day. Valida la fecha al construirla.
isBefore / isAfter / isEqualComparaciones legibles; existen variantes …OrEqual.
differenceInDays(otra)Diferencia con signo; absoluteDifferenceInDays() devuelve valor absoluto.
plusDays(n)Crea una nueva fecha desplazada.
toUtcMillis()Convierte la medianoche UTC a milisegundos.
UIDateTime
UIDateTime(y, m, d, hour, minute, second)
UIDateTime(y, m, d, hour, minute, second, millisecond, timeZoneId)Fecha y hora inmutable. Ofrece getDate(), comparaciones, toEpochMilliseconds(), difference() y differenceInMilliseconds().
UITimeSpan
UITimeSpan(totalMilliseconds)Duración con totales en milisegundos, segundos, minutos, horas o días; partes de días/horas/minutos/segundos; isNegative() y absolute().
UIDate inicio = new UIDate(2026, 9, 15);
UIDate examen = inicio.plusDays(30);
println(inicio.differenceInDays(examen));
UIDateTime entrada = new UIDateTime(2026, 9, 15, 9, 0, 0);
UIDateTime salida = new UIDateTime(2026, 9, 15, 11, 30, 0);
UITimeSpan duracion = salida.difference(entrada);
println(duracion.getTotalMinutes()); // 150UIDateComparator, UIDateTimeComparator y UICalendarEventDateComparator son comparadores auxiliares usados para ordenar colecciones.
Core
Core coordina tareas en cada fotograma. Solo puede existir una instancia ligada a un único PApplet.
Core.start(this)Crea la instancia o devuelve la existente si pertenece al mismo sketch.
Core.getInstance()Obtiene la instancia; lanza excepción si no se inició.
Core.isRunning()Indica si hay instancia activa.
Core.shutdown()Desregistra callbacks, destruye tareas y permite un reinicio limpio.
getTaskById(id)Busca una tarea por su entero positivo.
getTaskCount() / getTasksSnapshot()Consulta el estado sin exponer la colección interna.
signal(task, señal)Envía una señal a una tarea.
signal(type, señal)Envía a todas las tareas de un tipo.
signal(className, señal)Envía por nombre de clase.
letMeAlone()Desde una tarea, elimina las demás que no estén protegidas.
Señales
| Constante | Resultado |
|---|---|
SIGNAL_KILL | Marca para destruir, salvo protección. |
SIGNAL_PROTECT | Activa protección contra kill. |
SIGNAL_UNPROTECT | Retira la protección. |
Representación
El renderizado automático está activo. Usa setAutomaticRendering(false) y llama renderTasks() cuando necesites controlar las capas. setTaskCanvasScale() aplica una escala común a todas las tareas gráficas.
Task antes de Core.start(this) produce una excepción. Intentar iniciar el singleton con otro sketch también produce una excepción.Task
Una tarea encapsula estado y comportamiento actualizado por fotogramas. Se registra automáticamente al ejecutar su constructor.
Ciclo de vida que se sobrescribe
protected void initialize()Una vez, justo antes del primer frame().
protected void frame()Una vez por fotograma mientras la tarea esté viva.
protected void onDestroy()Una sola vez al destruirse.
protected void render()Dibujo; la implementación base representa graph con transformaciones.
import simplecore.*;
class Pelota extends Task {
Pelota(PImage imagen) {
setGraph(imagen).setPosition(80, 120).setZ(10);
}
protected void initialize() {
priority = 5;
}
protected void frame() {
advance(0, 2); // 0° = derecha
setAngle(angle + 1);
if (x > width + 50) kill();
}
protected void onDestroy() {
println("Pelota destruida: " + id);
}
}
void setup() {
size(640, 360);
Core.start(this);
new Pelota(loadImage("pelota.png"));
}Estado y API
id, type, className, father, liveFramesIdentidad, clasificación, relación y edad.
priorityLas prioridades mayores actualizan primero.
propertiesStringDict para datos adicionales.
kill() / setKillProtection()Controlan la vida y protección.
setGraph() / clearGraph()Asigna imagen de representación.
setPosition(), setZ(), setScale(), setAxisScale()Transformaciones encadenables.
setAngle(), setAlpha(), setTint(), setVisible()Apariencia encadenable.
getDist(task) / getAngle(task)Relación espacial con otra tarea.
advance(ángulo, distancia)Desplaza usando grados.
exists() / isDrawable()Consulta estado.
NetMessage, onNetMessage() ni conversiones de rutas. La comunicación de red puede añadirse después mediante una interfaz del proyecto.52 sketches: 26 parejas Desktop y Android
Cada ejercicio Desktop tiene una versión Android equivalente. Los nombres y la estructura se mantienen para que el alumno pueda comparar ambas plataformas línea por línea.
01 a 09
Botones, imagen, etiqueta, indicador, checkbox, slider, progreso, desplegable y pestañas.
10 a 18
Lista, tabla, entradas de texto y número, panel, chat, medidor RSSI y calendario.
19 a 21
Miniaplicaciones de login, confirmación modal y navegación mediante vistas.
22 a 25
SimpleCore: ciclo de vida, minijuego, partículas y reacción al ratón o al dedo.
26
UISwitch: valor booleano compacto, estado inicial y evento changed.
Convención de nombres
Por ejemplo, Desktop06Slider y Android06Slider forman una pareja. Cada carpeta contiene un sketch independiente cuyo archivo principal tiene el mismo nombre que la carpeta.
Principios didácticos
- Variables con nombres que explican su función.
- Un único concepto nuevo por ejemplo de control.
- Sin recursos externos: iconos y sprites se generan por código.
- Sin callbacks manuales de ratón o teclado; se utiliza el puente automático de SimpleUI.
Catálogo completo de clases
La tabla distingue las clases pensadas para sketches de las clases de soporte que normalmente usa la propia biblioteca.
| Clase | Desktop | Android | Función |
|---|---|---|---|
SimpleUI | ✓ | ✓ | Coordinador estático. |
UIElement | ✓ | ✓ | Base de controles. |
UIButton, UIImageButton | ✓ | ✓ | Botones. |
UILabel, UIIndicator | ✓ | ✓ | Información no interactiva. |
UICheckbox, UISwitch | ✓ | ✓ | Valores booleanos. |
UISlider, UIProgressBar | ✓ | ✓ | Valor y progreso. |
UIDropdown, UITabs | ✓ | ✓ | Selección entre opciones. |
UIList, UITable | ✓ | ✓ | Colecciones desplazables. |
UITextField, UITextArea, UINumberField | ✓ | ✓ | Entrada de datos. |
UIPanel | ✓ | ✓ | Agrupación visual. |
chatArea, ChatAreaMessage | ✓ | ✓ | Mensajería. |
UISignalMeter | ✓ | ✓ | Medidor RSSI. |
UICalendar, UICalendarEvent, UICalendarSelection | ✓ | ✓ | Calendario y agenda. |
UIDate, UIDateTime, UITimeSpan | ✓ | ✓ | Modelo temporal. |
UIView, UIViewManager, UIModal | ✓ | ✓ | Pantallas y diálogos. |
UIColorTheme, UIConfig, UIEventHandler, UIScaleMode | ✓ | ✓ | Configuración pública. |
UITextInputBase | ✓ | ✓ | Base abstracta de inputs. |
UIScrollState, UIGestureState, UIGestureAxis, UIGestureTarget | ✓ | ✓ | Soporte interno de interacción. |
UIDateComparator, UIDateTimeComparator, UICalendarEventDateComparator | ✓ | ✓ | Ordenación temporal. |
UIRect | ✓ | ✓ | Rectángulo auxiliar común. |
Core, Task | ✓ | ✓ | Motor común simplecore. |
Tipos de soporte
UIScrollState mantiene desplazamiento y objetivo; UIGestureState registra el gesto capturado; UIGestureAxis clasifica su eje; UIGestureTarget representa el destino; UITextInputBase normaliza la interfaz de inputs. Son públicos por compatibilidad, pero no es necesario instanciarlos para el uso normal.
Recetas y buenas prácticas
Un identificador único por control
El campo id permite localizar controles y depurar eventos. Usa nombres semánticos como "guardarAlumno" y evita reutilizarlos.
Orden de capas
Los controles se dibujan en el orden en que se añaden. Añade primero paneles y fondos; después campos y botones. Dropdowns y modales reciben tratamiento especial para quedar accesibles.
Comprueba acción y elemento
public void onUIEvent(UIElement element, String action, Object data) {
if (element.id.equals("edad") && action.equals("submitted")) {
Float edad = (Float)data;
if (edad != null) println("Edad: " + edad);
}
}Actualiza, no recrees
Crea los controles en setup() o en UIView.initialize(). Durante draw(), modifica su contenido con setters. No construyas y registres controles en cada fotograma.
Define una resolución de diseño
Escoge un ancho y un alto lógicos —por ejemplo 1280 × 720— y llama a setMode(1280, 720). Usa UIScaleMode.RESPONSIVE si el layout debe aprovechar el espacio adicional de ventanas redimensionables o pantallas con otra proporción.
Reorganiza solo cuando cambie el viewport
En un layout responsive, guarda el último valor de getLogicalWidth() y getLogicalHeight(). Recalcula posiciones y tamaños únicamente cuando cambien; evita hacerlo innecesariamente cada fotograma.
Limpieza
SimpleUI.detach() y Core.shutdown() existen para reinicios controlados y tests. En el cierre normal, ambas partes usan callbacks dispose.
Licencia MIT
SimpleUI y SimpleCore han sido diseñadas y desarrolladas por Luis López Martínez. Copyright © 2026 Luis López Martínez.
La biblioteca se distribuye bajo licencia MIT. Permite usar, copiar, modificar, fusionar, publicar, distribuir, sublicenciar y vender copias, conservando el aviso de copyright y la licencia.
LICENSE incluido en la raíz de la biblioteca para leer el texto legal completo.Datos de esta versión
| Nombre | SimpleUI |
|---|---|
| Versión | 0.5.1 |
| Diseño y desarrollo | Luis López Martínez |
| Copyright | © 2026 Luis López Martínez |
| Licencia | MIT |
| Paquetes | simpleui.desktop, simpleui.android, simplecore |
| Artefacto | library/SimpleUI.jar |
| Última actualización | 24 de julio de 2026 |
| Palabras clave | GUI, widgets, controles, interfaces, Desktop, Android, Processing |
Compatibilidad comprobada
- Windows: compilación y pruebas completas con Processing 4.5.2.
- Android: compilación con Android Mode 4.6.1, Android API 33 y conversión D8.
- macOS y Linux: pendientes de verificación por la comunidad.
No incluye dependencias de ejecución de terceros. Processing 4 es necesario y los sketches Android requieren instalar Android Mode.
Código fuente y seguimiento del proyecto · Descargar la última versión