Por qué la accesibilidad no es para «débiles», sino para la calidad del código
\n\nCuando escribimos en C++, estamos acostumbrados a pensar en rendimiento, memoria y velocidad. Pero hay otro aspecto que a menudo se pasa por alto: la accesibilidad. No es solo un término de moda del mundo del desarrollo web. En C++, la accesibilidad de las aplicaciones es la posibilidad de que personas con discapacidades (visuales, auditivas, motoras) usen su software en igualdad de condiciones con los demás.
\n\nImagínese: ha creado un editor gráfico increíble o una utilidad de consola. Pero si no se puede leer con un lector de pantalla o no se puede controlar con el teclado, está excluyendo al 15-20% de los usuarios. Además, la accesibilidad suele ser un requisito legal (por ejemplo, en EE. UU. - Sección 508, en Europa - EN 301 549).
\n\nEn este artículo, analizaremos cómo implementar las mejores prácticas a11y (a11y es la abreviatura numérica de accesibilidad) en proyectos de C++ sin sacrificar el rendimiento. ¡Allá vamos!
\n\nPor dónde empezar: principios básicos del código inclusivo
\n\nAntes de meterse en el código, recuerde los tres pilares:
\n\n- \n
- Perceptibilidad — la información debe ser accesible al menos a través de un sentido (vista, oído, tacto). \n
- Operabilidad — la interfaz debe funcionar con teclado, voz o interruptores. \n
- Comprensibilidad — el comportamiento de los elementos es predecible, los errores son comprensibles. \n
En C++, esto es especialmente importante porque a menudo trabajamos con API de bajo nivel donde se pierde la semántica. Por ejemplo, al dibujar un botón con OpenGL, no obtendrá soporte automático para lectores de pantalla; debe agregarlo manualmente.
\n\nMarcado semántico en GUI de C++: Qt y más
\n\nLa forma más común de agregar accesibilidad en C++ es usar el framework Qt. Tiene soporte integrado a través de QAccessibleInterface. Pero incluso si escribe en WinAPI puro, existe IAccessible.
Ejemplo: haciendo un botón accesible
\n\nSupongamos que tiene un botón personalizado dibujado con QPainter. Sin accesibilidad, el lector de pantalla verá simplemente un «rectángulo». Lo corregimos:
\n\n#include <QAccessible>\n#include <QAccessibleWidget>\n#include <QPushButton>\n\nclass AccessibleButton : public QAccessibleWidget {\npublic:\n explicit AccessibleButton(QWidget* widget)\n : QAccessibleWidget(widget, QAccessible::Button) {}\n\n QString text(QAccessible::Text t) const override {\n if (t == QAccessible::Name) {\n auto* btn = qobject_cast<QPushButton*>(widget());\n return btn ? btn->text() : QString();\n }\n return QAccessibleWidget::text(t);\n }\n};\n\n// Uso:\nQPushButton* btn = new QPushButton("Enviar");\nQAccessible::registerAccessibleFactory(\n [](QObject* obj) -> QAccessibleInterface* {\n if (auto* btn = qobject_cast<QPushButton*>(obj)) {\n return new AccessibleButton(btn);\n }\n return nullptr;\n }\n);\n\nAhora el lector de pantalla leerá «Enviar, botón». ¿Magia? No, simplemente código inclusivo.
\n\nAccesibilidad en aplicaciones de consola en C++
\n\nPodría parecer que la consola es cosa del pasado. Pero muchas utilidades, pipelines de CI/CD y aplicaciones de servidor funcionan precisamente en la terminal. ¿Cómo hacerlas accesibles?
\n\nSalida correcta para lectores de pantalla
\n\nEl lector de pantalla (por ejemplo, NVDA, JAWS) lee la consola línea por línea. Si muestra una tabla con caracteres ASCII, es una pesadilla. Es mejor usar una salida estructurada:
\n\n#include <iostream>\n#include <string>\n#include <vector>\n\nstruct User {\n std::string name;\n int age;\n};\n\nvoid printAccessibleTable(const std::vector<User>& users) {\n // Amigable para el lector de pantalla: primero el encabezado, luego los datos\n std::cout << "Tabla de usuarios:" << std::endl;\n for (const auto&