sábado, 10 de diciembre de 2016

Curso de Delphi - Capítulo 4. Condicionales


Por fín podemos continuar con el curso de Delphi sobre Lazarus.
En este cuarto episodio os vamos a explicar las sentencias condicionales que existen en Pascal y cómo utilizarlas.

En concreto veremos:

  • If... then
  • If... then begin end
  • If... then... else
  • If... then anidados
  • If con condiciones compuestas
  • Sentencia Case

Además como novedad en ese episodio os proponemos una serie de ejercicios para que practiquéis en casa y que veremos resueltos en próximos episodios.   

Esperando que sea de vuestro total agrado os dejamos con el vídeo.


Capítulos:
Compartir:

lunes, 5 de diciembre de 2016

Cómo instalar NetBeans GlassFish y el JDK J2EE

He vuelto a retomar el canal de youtube y para celebrarlo os traigo un video explicando como instalar NetBeans junto con el JDK J2EE y GlassFish.

http://ffgrouppakistan.com/wp-content/uploads/2015/12/netbeans-logo.png


Proximamente llegarán más vídeos con instalaciones y proseguiremos el curso de Lazarus mientras empezamos uno de Java EE. Si tenéis cualquier sugerencia podéis utilizar las redes sociales, los comentarios de este post o los del video en cuestión.


Si tienes cualquier duda o comentario recuerda que puedes exponerlo aquí o bien mediante nuestro twitter y facebook.


Compartir:

martes, 29 de noviembre de 2016

Truco Java - Establecer formato moneda en columna JTable

Hoy os voy a mostrar como poner el formato moneda (currency) en un campo de vuestra JTable.

De la misma manera que en el truco anterior, nos crearemos una clase dentro del paquete componentes de nuestra aplicación heredando de DefaultTableCellRenderer.

import java.awt.Component;
import java.text.NumberFormat;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;

public class CurrencyCellRenderer extends DefaultTableCellRenderer {
 
    private static final NumberFormat FORMAT = NumberFormat.getCurrencyInstance();

    @Override
    public final Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {
        final Component result = super.getTableCellRendererComponent(table, value,
                isSelected, hasFocus, row, column);
        if (value instanceof Number) {
            setHorizontalAlignment(JLabel.RIGHT);
            setText(FORMAT.format(value));
        } else {
            setText("");
        }
        return result;
    }
}

La utilización es similar al caso TimestampCellRenderer:

public void LlenarTabla(JTable tablaListadoVentas, boolean inicializar) {
        DefaultTableModel modeloTabla = new DefaultTableModel (){
            @Override //Establecemos todas las celdas como no editables
            public boolean isCellEditable(int row, int column) {               
                return false;
            }            
        };
        
        tablaListadoVentas.setModel(modeloTabla);
        
        modeloTabla.addColumn("Venta");
        modeloTabla.addColumn("Id. Cliente");
        modeloTabla.addColumn("Nombre");
        modeloTabla.addColumn("Id. Empleado");
        modeloTabla.addColumn("Nombre");
        modeloTabla.addColumn("Fecha y hora");
        modeloTabla.addColumn("Nº Artículos");
        modeloTabla.addColumn("Importe Total");                        
        
        Object[] columna = new Object[8];       
        
        tablaListadoVentas.getColumnModel().getColumn(5).setCellRenderer(new TimestampCellRenderer());
        tablaListadoVentas.getColumnModel().getColumn(7).setCellRenderer(new CurrencyCellRenderer());

Si tienes cualquier duda o comentario recuerda que puedes exponerlo aquí o bien mediante nuestro twitter y facebook.
Compartir:

jueves, 3 de noviembre de 2016

Truco Java - Establecer formato fecha y hora en columna JTable

El truco que os traigo hoy es producto de una necesidad que me surgió durante la elaboración del proyecto del curso de Java que estoy haciendo. La necesidad vino cuando necesité establecer formato fecha/hora a un campo de un JTable que contenia un valor Timestamp obtenido de MySQL.



Lo que tenemos que hacer es crearnos una clase (en mi caso estas clases las meto siempre en un paquete llamado "componentes" para tenerlo todo organizado) que herede de DefaultTableCellRenderer y posteriormente utilizarla en nuestra columna de JTable.

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import javax.swing.table.DefaultTableCellRenderer;

public class TimestampCellRenderer extends DefaultTableCellRenderer {

    DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");

    public TimestampCellRenderer() {
        super();
    }

    public void setValue(Object value) {
        if (formatter == null) {
            formatter = DateFormat.getDateInstance();
        }
        setText((value == null) ? "" : formatter.format(value));
    }
}

En la linea SimpleDateFormat podemos establecer el formato de fecha y hora que nosotros necesitemos. Se me ocurre como mejora añadir un parametro al constructor para poder pasar la cadena de formato por ejemplo.

La utilización es sencilla: Suponiendo que nuestro JTable se llame tablaListadoVentas y una vez establecido el modelo de la misma:

    public void LlenarTabla(JTable tablaListadoVentas, boolean inicializar) {
        DefaultTableModel modeloTabla = new DefaultTableModel (){
            @Override //Establecemos todas las celdas como no editables
            public boolean isCellEditable(int row, int column) {               
                return false;
            }            
        };
        
        tablaListadoVentas.setModel(modeloTabla);
        
        modeloTabla.addColumn("Venta");
        modeloTabla.addColumn("Id. Cliente");
        modeloTabla.addColumn("Nombre");
        modeloTabla.addColumn("Id. Empleado");
        modeloTabla.addColumn("Nombre");
        modeloTabla.addColumn("Fecha y hora");
        modeloTabla.addColumn("Nº Artículos");
        modeloTabla.addColumn("Importe Total");                        
        
        Object[] columna = new Object[8];       
        
        tablaListadoVentas.getColumnModel().getColumn(5).setCellRenderer(new TimestampCellRenderer());


Si tienes cualquier duda o comentario recuerda que puedes exponerlo aquí o bien mediante nuestro twitter y facebook.
Compartir:

lunes, 31 de octubre de 2016

¿Qué es un ataque DDoS? ¿Cómo podemos evitarlo?

El Viernes 21 de Octubre de 2016 se produjo el mayor y más importante ataque DDoS de los últimos años. El ataque fue dirigido hacia los servicios DynDNS y dejo fuera de combate a decenas de web y servicios como por ejemplo Twitter, Reddit, Github, Amazon, Spotify



Lo grave del asunto es que el ataque al parecer fue perpetrado gracias a una vulnerabilidad existente en dispositivos IoT (Internet de las cosas), como son los electrodomésticos conectados a la red.


¿Que es un ataque DDos?

Vayamos por partes;  Un ataque de denegación de servicio (DoS) es un ataque dirigido hacia una red o sistema de computadoras que provoca que el mismo deje de responder a los usuarios. Esto ocasiona que el sistema esté fuera de línea el tiempo que dura el ataque más el tiempo de restablecimiento del sistema que suele oscilar entre 20 minutos y varias horas en el peor de los casos.

El caso que nos ocupa es una ampliación de este ataque y sus siglas DDoS corresponden a ataque de denegación de servicio distribuido o Distributed Denial of Service, en el que el ataque se lleva a cabo desde cientos o miles de puntos diferentes hacia el mismo objetivo.



Existen diferentes tipos de ataque, pero básicamente se trata de enviar un flujo tal de peticiones que el sistema no puede atenderlas por lo que acaba tirando el servicio por seguridad. Otros ataques pueden suponer interrupciones de componentes físicos de red o incluso alteración de las tablas de enrutamiento.


¿Por qué es tan popular el ataque DDoS?

Los ataques DDoS se han vuelto muy populares debido a que el objetivo no tiene por que tener ninguna vulnerabilidad, ya que son ataques de infraestructura. Por esto cualquiera podría comprar un pack de ataque DDoS por unos 150€ y mantener fuera de línea a un rival de League of Legends por ejemplo (Sí, esto ha pasado). Ojo, antes he mencionado que se ataca desde cientos o miles de ordenadores y es que estos ordenadores sí que suelen estar afectados por alguna clase de vulverabilidad (como Mirai en el internet de las cosas) o malware.


¿Qué se busca con los ataques DDoS?

Aquí debemos tener en cuenta los tipos de ataque; estos pueden ser personalizados, los cuales no tienen mucha repercusión mediática y suelen buscar un objetivo concreto (dejar fuera de línea a un rival o tirar el servidor del examen de la universidad) o globales, los cuales buscan una gran repercusión mediática, suelen estar reivindicados por organizaciones o grupos hacktivistas y sirven para que el mundo les preste atención.

¿Como podemos evitar los ataques DDoS?

No se puede… sin más, hoy en día es imposible evitar este tipo de ataques debido a que las causas son los propios mecanismos de seguridad de nuestras infraestructuras informáticas. Hace unos años podríamos pensar que si todos nuestros ordenadores estuvieran libres de malware, no podrían pertenecer a botnets (redes de ordenadores zombies controlados por un mismo malware y que son capaces de perpetrar ataques DDoS dirigidos) y entonces sería mucho más complicado realizar estos ataques pero, ay amigos, bienvenidos al internet de las cosas.


El internet de las cosas y Mirai.

Actualmente no son pocos los hogares que disponen de más de un ordenador conectado a internet sin siquiera darse cuenta. ¿Tienes una SmartTv? ¿un frigorífico conectado a internet? ¿Un ebook, tablet, videoconsola? ¿Quizá tengas una de esas nuevas bombillas inteligentes o un Chromecast? ¿Una camara IP? Podría seguir así mucho rato pero aunque no tengas nada de esto, seguro que tienes un router en casa ¿verdad? ¿Le has cambiado la contraseña? :D
¿Por que os cuento esto? Bueno, todos esos artículos son susceptibles de ser participes en la mayor botnet jamás creada, Mirai.

Mirai es capaz de convertir sistemas Linux en bots controlados remotamente y además ni siquiera necesita crackearlos ya que la mayoría de nosotros no se preocupa de cambiar la contraseña genérica de estos dispositivos. Mirai puede afectar a impresoras, camaras de vigilancia o routers caseros y hay poco que podamos hacer.



Este es un problema que tiene difícil solución y quizá sería un buen momento para plantearnos si realmente necesitamos tantos dispositivos inteligentes o sería más sensato usar nuestra inteligencia y dejar de ser tan cómodos.

Y tú. ¿Tienes muchos aparatos conectados a internet?

Compartir:

jueves, 27 de octubre de 2016

Truco C# - Eliminar / Matar procesos Windows por nombre o id

En este post os voy a enseñar una manera sencilla de eliminar procesos concretos por nombre o id mediante programación.

Para poder hacer uso de este truco vamos a necesitar añadir System.Diagnostics a nuestro programa ya que haremos uso de la clase Process. Una vez hecho esto vamos a definir 3 métodos, uno para matar procesos por su id de proceso y dos que irán por nombre de proceso; el primero eliminará la primera ocurrencia y el segundo eliminará todos los procesos con el mismo nombre (el proceso "Chrome" puede ser un buen ejemplo para probarlo).

Matar tarea por Id.

 
        private void KillTaskById(int taskid)
        {
            try
            {
                Process proceso = Process.GetProcessById(taskid);
                proceso.Kill();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

Matar tarea por Nombre. Primera ocurrencia.

        private void KillTaskByName(string taskName)
        {
            try
            {
                Process[] procesos = Process.GetProcessesByName(taskName);
                procesos[0].Kill();
            } 
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

Matar tarea por Nombre. Todas las ocurrencias.

 
        private void KillAllTasksByName(string taskName)
        {
            try
            {
                foreach (Process proceso in Process.GetProcessesByName(taskName))
                {
                    proceso.Kill();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

Probadlo y dejar en los comentarios que os ha parecido.

Si tienes cualquier duda o comentario recuerda que puedes exponerlo aquí o bien mediante nuestro twitter facebook.
Compartir:

miércoles, 26 de octubre de 2016

Truco C# - Listar todos los servicios de un webservice

Hacía ya mucho tiempo que no posteaba nada, mas por falta de tiempo que por otra cosa, pero hoy os traigo una nueva entrada con un truco para C#.

Si habéis leido el título ya intuireis de que va el truco de hoy. Se trata, ni más ni menos de cómo obtener la lista de servicios publicados en un webservice.

Para que el método funcione lo único que necesitais es la url de un descriptor de webservice (acabará en ?wsdl o ?singleWSDL) para pasarla como parametro al método GetWsdlMethods que os describo a continuación.


 
        private string[] GetWsdlMethods(string wsdlUrl)
        {
            List<string> services = new List<string>();

            try
            {
                XmlTextReader myStreamReader = new XmlTextReader(wsdlUrl);

                ServiceDescription wsdl =
                   ServiceDescription.Read(myStreamReader);

                txtMethods.Clear();

                foreach (PortType pt in wsdl.PortTypes)
                {

                    services.Add(string.Format("PortType {0}", pt.Name));
                    services.Add("\r\n----------------------------------------");
                    foreach (Operation op in pt.Operations)
                    {
                        services.Add(string.Format("\r\n{0}", op.Name));
                    }
                }
            }
            catch
            {
                services.Add("ERROR READING WDSL URL");
            }

            return services.ToArray();
        }



Probadlo y dejar en los comentarios que os ha parecido.

Si tienes cualquier duda o comentario recuerda que puedes exponerlo aquí o bien mediante nuestro twitter facebook.
Compartir:

jueves, 25 de agosto de 2016

Cómo bloquear / desactivar / eliminar los anuncios de Skype



Todos los que usamos Skype nos hemos acostumbrado a convivir con los anuncios que la aplicación nos muestra pero, ¿sabíais que se pueden desactivar de una manera muy sencilla? Sigue leyendo y te explico cómo.


Compartir:

jueves, 30 de junio de 2016

Truco Java - Uso de ListIterator

Hoy más que un truco os voy a poner un ejemplo de utilización de la clase ListIterator
ListIterator es un iterador secuencial que posibilita recorrer listas en cualquier sentido. Hay que tener presente que la posición de un iterador no representa ningún valor real de la lista, siempre estará entre dos elementos, al principio o al final.



En el ejemplo vamos a recorrer un Array de cadenas extrayendo los valores numéricos y posteriormente recorriendo la lista hacia adelante y hacia atrás.

 
package TrucosIExpression;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.ListIterator;

/**
 *
 * @author InvalidExpression
 */
public class Truco1 {

    /**
     * Metodo que extray todos los valores numéricos de un array de cadenas
     * y lo devuelve en un ArrayList
     * @param cadenas String[] .
     * @return ArrayList con valores numericos extraidos.
     */
    public ArrayList extraerNumeros(String[] cadenas) {
        if (cadenas == null) {
            throw new IllegalArgumentException("Parámetro erroneo.");
        } else {
            ArrayList arrayCadenas = new ArrayList();
            arrayCadenas.addAll(Arrays.asList(cadenas));
            ListIterator listaIterador;
            listaIterador = arrayCadenas.listIterator();
            while (listaIterador.hasNext()) {
                String cadena = (String) listaIterador.next();
                try {
                    Integer numero = new Integer(cadena);
                } catch (NumberFormatException e) {
                    listaIterador.remove();
                }
            }
            return arrayCadenas;
        }
    }

    /**
     * Metodo main.
     *
     * @param args String[] args.
     */
    public static void main(String[] args) {
        Truco1 trucoIterator = new Truco1();
        String[] cadenas = {"SILLA","5", "1", "4", "MESA", 
                            "8", "ZAPATO", "CERVEZA", "10", "12"};
        ArrayList arrayNumeros = trucoIterator.extraerNumeros(cadenas);
        ListIterator iterador = arrayNumeros.listIterator();
        //Recorremos de principio a fin con hasNext
        while (iterador.hasNext()) {
            System.out.println(iterador.next());
        }
        //Recorremos desde el final hasta el principio.
        while (iterador.hasPrevious()) {
            System.out.println(iterador.previous());
        }
    }
}

El resultado de la ejecución de este pequeño programa en NetBeans sería el siguiente:


Si necesitáis más información sobre ListIterator podéis encontrarla aquí.

Si tienes cualquier duda o comentario recuerda que puedes exponerlo aquí o bien mediante nuestro twitter facebook.
Compartir:

martes, 28 de junio de 2016

Truco Delphi - Enviar emails usando el servicio Gmail de Google

En el truco de hoy os voy a enseñar como podéis enviar correos electrónicos desde vuestra aplicación Delphi mediante vuestra cuenta Gmail.


Para ello vamos a hacer uso de los componentes Indy disponibles en cualquier versión de RAD Studio (en el truco se utiliza la versión XE8 pero está testeado en XE5 también).

Vamos a crearnos una función SendGMail con el siguiente código:
 
procedure SendGmail(pUsuario, pPassword, pAsunto, pCuerpo, pDestino : string);
var
  Smtp : TidSMTP;
  ManejadorSSL : TidSSLIOHandlerSocketOpenSSL;
  Mensaje: TIdMessage;
begin
  ManejadorSSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  with ManejadorSSL do
  begin
   Destination := 'smtp.gmail.com:587';
   Host := 'smtp.gmail.com';
   MaxLineAction := maException;
   Port := 587;
   SSLOptions.Method := sslvTLSv1;
   SSLOptions.Mode := sslmUnassigned;
   SSLOptions.VerifyMode := [];
   SSlOptions.VerifyDepth := 0;
  end;

  Smtp := TIdSMTP.Create( nil );

  with Smtp do
  begin
    IoHandler := ManejadorSSL;
    Host := 'smtp.gmail.com';
    Port := 25;
    Username := pUsuario;
    Password := pPassword;
    UseTLS := utUseExplicitTLS;
  end;

  Mensaje := TIdMessage.Create(nil);
  with Mensaje do
  begin
    Clear;
    Subject := pAsunto;
    Body.Text := pCuerpo;
    Recipients.Add;
    Recipients.Items[0].Address := pDestino;
  end;

  Smtp.Connect;
  if smtp.Connected then
  begin
    smtp.Send(Mensaje);
    smtp.Disconnect;
  end;

  FreeAndNil(Smtp);
  FreeAndNil(Mensaje);
  FreeAndNil(ManejadorSSL);

end;


Y ya está, solamente tendremos que llamar a esta función con los parámetros relativos a nuestra cuenta para enviar nuestro correo.

En lugar de crear los objetos dinámicamente, podéis pegar objetos directamente desde la paleta de componentes en vuestro formulario y ahorraros el create; si lo hacéis dinámicamente no olvidéis incluir en el uses las referencias necesarias:

uses
  [...] IdMessage, IdIOHandler, IdIOHandlerSocket, IdIOHandlerStack,
  IdSSL, IdSSLOpenSSL, IdBaseComponent, IdComponent, IdTCPConnection,
  IdTCPClient, IdExplicitTLSClientServerBase, IdMessageClient, IdSMTPBase,
  IdSMTP,IdAttachmentFile,IdGlobal;

Observaréis que falta la opción de adjuntar algún archivo, pero eso lo vamos a dejar para futuros trucos.

Si tienes cualquier duda o comentario recuerda que puedes exponerlo aquí o bien mediante nuestro twitter facebook.

Compartir:

jueves, 23 de junio de 2016

Truco Delphi - MessageBox organizados y personalizados.

Si eres, o has sido, programador Delphi, seguramente te has encontrado muchas aplicaciones donde se utiliza la función Showmessage, MessageBox o Messagedlg o incluso todas a la vez de manera desorganizada y no unificada.


En este truco/post os voy a mostrar como organizar vuestros mensajes de aplicación en una única unidad y como personalizarlos con vuestros propios iconos sin necesidad de crear formularios específicos para ellos.

Mi recomendación es que utilicéis siempre MessageBox, por dos motivos:
  1. MessageBox es una función de la Api de Windows, por tanto, los textos de los botones estarán localizados al idioma del sistema.
  2. Permite una mayor personalización y control de los mensajes mostrados.
En toda aplicación suelen utilizarse, al menos, tres tipos de mensajes de diálogo con el usuario; Mensajes de error, mensajes de aviso y mensajes de pregunta.

Mi recomendación es que os creéis una unidad donde agrupéis todos esos mensajes de manera que podáis utilizarlos en toda la aplicación, por ejemplo algo así:

  
unit UDialogos;

interface

uses Windows;

procedure MensajeError(owner: HWND; p_texto :string);
procedure MensajeAviso(owner: HWND; p_texto :string);
function Pregunta(owner: HWND; p_texto, p_titulo: string) : boolean;

implementation

procedure MensajeError(owner: HWND; p_texto :string);
begin
  MessageBox(owner, pchar(p_texto), 'Error',
               MB_ICONERROR or MB_OK or MB_TASKMODAL)
end;

procedure MensajeAviso(owner: HWND; p_texto :string);
begin
  MessageBox(owner, pchar(p_texto),'Aviso',
               MB_ICONINFORMATION or MB_OK or MB_TASKMODAL )
end;

function Pregunta(owner: HWND; p_texto, p_titulo: string) : boolean;
begin
  result := MessageBox(owner, pchar(p_texto), pchar(p_titulo),
               MB_ICONQUESTION or MB_YESNO or MB_TASKMODAL) = IDYES
end;

end.


De esta manera tendremos todos los mensajes localizados en una unidad de nuestra aplicación y a nuestra disposición para cuando los necesitemos.

Es importante utilizar correctamente el parámetro "owner" de esas funciones y pasárles siempre el "Handle" del formulario que llama a la función ("Self.Handle") para que los diálogos sepan delante de quién deben mostrarse.

Si no os gustan los iconos por defecto que muestra Windows, siempre podéis utilizar los vuestros utilizando "MB_USERICON", pero en este caso deberéis utilizar la función MessageBoxIndirect.

Supongamos que tenemos un icono en los recursos de nuestra aplicación llamado 'ICONICO' y que queremos mostrarlo en un mensaje de dialogo concreto, escribiríamos lo siguiente:

  
procedure MensajePersonalizado(owner: HWND; p_texto, p_titulo :string);
var
  flags : uint;
  MsgPars: TMsgBoxParams;
begin
  flags := MB_USERICON or MB_OK or MB_DEFBUTTON1 or MB_TASKMODAL;

  //Establecemos los parámetros
  with MsgPars do
  begin
    cbSize := SizeOf(MsgPars);
    hwndOwner := owner;
    hInstance := Sysinit.hInstance;
    lpszText := PChar(p_texto);
    lpszCaption := pchar(p_titulo );
    dwStyle := flags;
    lpszIcon := 'ICONICO'; //Nuestro icono en los recursos
    dwContextHelpId := 0;
    lpfnMsgBoxCallback := nil;
    dwLanguageId := LANG_NEUTRAL;
  end;

  MessageBoxIndirect(MsgPars);

end;



Una última consideración sobre utilizar MB_OKCANCEL o MB_YESNO. Cualquier flag que incluya OK y/o CANCEL responderá a las teclas "Intro" para el OK y "Escape" para el CANCEL, es decir, si utilizáis MB_YESNO, "intro" y "escape" no funcionarán, si utilizáis MB_OKCANCEL, si que lo harán.

Si tienes cualquier duda o comentario recuerda que puedes exponerlo aquí o bien mediante nuestro twitter facebook.
Compartir:

martes, 21 de junio de 2016

¿Qué pasaría si todo el mundo fuese capaz de programar? Estamos a punto de averiguarlo.


Podemos estar entrando en una era en la que cualquiera es capaz de hacer programas, a pesar de que no sepan programación – al menos no de la manera en la que la mayoría nosotros lo entendemos ahora mismo.

He empezado a jugar con una aplicación para iPad llamada Ready, que permite a los más pequeños hacer pequeños juegos, aplicaciones sencillas, y proyectos digitales creativos. Utiliza una sencilla interfaz “drag-and-drop” (arrastra y suelta) para crear objetos, cambiar sus propiedades, y hacer que interactúen entre ellos o con el usuario.


Crear una pelota, proporcionarle “físicas” para que responda a la gravedad; convertirla en goma para que “rebote” sobre las superficies; hacer una barra que se mueva de izquierda a derecha con los cursores; construir un muro de bloques que desaparecen cuando son golpeados por la pelota y listo… tenemos un Arkanoid de toda la vida.

Lo que WYSISWYG (lo que ves es lo que obtienes) hizo por la creación de documentos, lo hacerReady por la programación. Pero los efectos podrían ir más allá que el mero ahorro de tiempo.

Programación Drag-and-Drop

Ready realmente es un escritorio de Unity, el motor de juego multiplataforma que a su vez está basado en C y C++. Al permitir a los niños desarrollar juegos simplemente utilizando drag-and-drop e interfaces if/then, Ready sitúa a jóvenes desarrolladores un nivel por encima de lo que podríamos considerar como código “real” – pero sigue permitiéndoles crear desde cero.

Yendo más allá, imagino que los usuarios, con el tiempo, serán capaces de profundizar lo suficiente para crear sus propios objetos y elementos – quizá incluso ofreciéndolos a otros en un mercado digital. Piensa en un Minecraft, pero construido desde el principio para ser una plataforma creativa completamente abierta.


Las buenas ideas son más valoradas que el buen código.

Jugar con estas herramientas hace que me pregunte si, dentro de poco, todos nosotros estaremos desarrollando de esta manera. ¿Podría "Ready" y otros escritorios similares hacer por la programación lo que hizo Photoshop por las imágenes o Word por la creación documental?. Si lo hace, entonces la creación de aplicaciones por “no-programadores” con buenas ideas podría ser inminente. Aunque el código puede no ser tan elegante ni optimizado como si un desarrollador lo escribiera desde cero, este tipo de aplicaciones serían válidas como prototipos.


Cuanto más fáciles sean los ordenadores, más se alejan los usuarios de ser programadores.


Un conjunto configurable de elementos y objetos como "Ready" puede que no tenga en cuenta las infinitas posibilidades y nuevas innovaciones de la codificación pura, pero la mayoría de los programas actualmente no usan ese tipo de innovación de todos modos. Pensemos en Uber. Una aplicación GPS enlazada a una aplicación de cobros enlazada a una aplicación de citas. Y los nuevos programadores no van a intentar crear nada tan robusto como una plataforma de intercambio de ficheros global ni nada parecido.

Antes de que los más puristas empecéis a atacar el concepto de una programación que se dirige más hacia PowerPoint que hacia Python, consideremos por un momento que podríamos decir lo mismo sobre cualquier lenguaje de programación. Después de todo C++ o cualquier lenguaje de alto nivel, pasa a través de un compilador para convertirse en algo que la mayoría de nosotros es incapaz de leer. Y el programa en sí mismo se asienta sobre un sistema operativo, y lenguaje ensamblador, e instrucciones máquina, y arquitectura basada en chips… Puedes considerarte a ti mismo un desarrollador de software competente sin haber bajado jamás a ese nivel de comprensión.

Créeme, yo me encuentro entre los puristas, resentidos por la aparición del Mac y otras interfaces que parecían diseñadas intencionadamente para hacer la computación “más fácil” simplemente distanciando a los usuarios de las funciones básicas. Microsoft hizo que invocásemos a “the wizard” (el mago), como si fuera algo misterioso que las aplicaciones y sus extensiones acabasen en el directorio correcto. Cuanto más fáciles sean los ordenadores, más se alejan los usuarios de ser programadores. Echo de menos mi fichero autoexec.bat



Más que un simple ahorro de tiempo.


Ready” me hace pensar que la simplificación de las interfaces de usuario puede, finalmente, ofrecer algo distinto a un simple distanciamiento del código: el poder. La gratificación instantánea de construir algo en “Ready” proporciona esa sensación de poder – casi como ser el autor de Hypercard en los primeros días de Macintosh o construir un sitio en WordPress cuando mi ambición y necesidades superan claramente mis habilidades. Hay un plug-in de WordPress para casi todo lo que puedo querer hacer en mi sitio.

Una cosa es cierta, si la gente no tiene que escribir código, puede que nunca entiendan cómo funcionan realmente las cosas. Estarán limitados por las posibilidades ofrecidas por los creadores de las plataformas, a través de las cuales ensamblarán componentes prefabricados en aplicaciones y otras experiencias digitales.

Del mismo modo que dimos la bienvenida a los usuarios de AOL al Internet real, “Ready” y otras aplicaciones, pueden hacer entrar a legiones de “desarrolladores civiles” en la industria de los juegos y las aplicaciones. Con la democracia viene un poco de embrutecimiento. No van a ser maestros en programación, pero tampoco son maestros en música los compositores que escriben las canciones de las bandas de garaje. Esta puede ser la realidad creativa “mash-up” hacia la que vamos. (El mashup es un género musical que consiste en la creación de un nuevo tema mediante la combinación de fragmentos (loops), instrumentos concretos, pistas vocales (a cappellas) y pistas instrumentales a cachitos o enteras de otros temas anteriormente ya realizados por otros). Hay mucho que aprender si quieres estar al día. Yo era bueno en Pascal, pero hoy en día los lenguajes de programación son muy duros y puede que no compense lo suficiente aprenderlos.

Este puede ser el momento en que finalmente entramos en la era de “Bandas de Garage” de la creación de aplicaciones y juegos. Las cosas pueden ponerse complicadas, pero también serán menos comerciales, brillantes y funcionalmente opacas.

A pesar de todo, en un mundo en el que escribir código se ha convertido en una habilidad rara y valiosa, una plataforma como “Ready” permite a las masas experimentar el poder de la creación.

Esa experiencia, por si misma, puede ser más importante que cualquiera de las aplicaciones que creemos. Cambia la manera en la que percibimos el panorama digital en el que gastamos gran parte de nuestras vidas. Ahora mismo todo es software creado por otros, pero con las herramientas correctas, podría ser el software que imaginemos y creemos por nosotros mismos.

Estoy listo para eso.


Artículo por: Douglas Rushkoff. Traducido y adaptado por: Miguel Montero Gámez.


Si tienes cualquier duda o comentario recuerda que puedes exponerlo aquí o bien mediante nuestro twitter facebook.
Compartir:

lunes, 20 de junio de 2016

Truco Delphi - Ocultar icono de nuestra aplicación en barra de tareas

Hoy toca un truco rápido, fácil y para toda la familia que consiste en ocultar el icono de nuestra aplicación de la barra de tareas en Delphi.

¿Para que sirve esto? Bueno, eso depende; imaginad que necesitáis hacer una aplicación iconizada en el área de notificaciones (Al lado del reloj) y que queréis que cuando se muestre no aparezca el icono en la barra de tareas (igual que el reloj de Windows por ejemplo).

Para ello solamente tendremos que anular la función CreateParams de la clase TForm para codificar nosotros mismos lo que necesitamos de la siguiente manera:
  
TfrmPrincipal = class(TForm)
  private
    { Private declarations }
  protected
    procedure CreateParams(var Params: TCreateParams); override;
  public
    { Public declarations }
  end;

procedure TfrmPrincipal.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.ExStyle := Params.ExStyle and not WS_EX_APPWINDOW;
  Params.WndParent := Application.Handle;
end;

Si tienes cualquier duda o comentario recuerda que puedes exponerlo aquí o bien mediante nuestro twitter y facebook.
Compartir:

viernes, 17 de junio de 2016

Truco Java - Añadir imágenes a un JTable desde un campo Blob en MySQL

Hoy hemos realizado una encuesta a través del twitter del blog preguntandoos sobre que lenguaje queríais el siguiente truco y ha ganado JAVA.

Por suerte estoy realizando un master de JAVA ahora mismo y a diario me surgen problemas y dudas que voy solventando y que, seguramente, sean las mismas que tengáis vosotros si estáis empezando con este lenguaje.

En el truco que nos ocupa hoy os voy a enseñar cómo solucioné la cuestión de mostrar un campo de imagen (tipo BLOB en MySQL) en un JTable.


Os pondré el código que rellena la tabla y luego os destacaré un par de secciones que son las que considero más importantes.

Este es el código en cuestión:

    /**
     * Procedimiento LlenarTabla
     * Utilizando el procedimiento modeloImagen.listImagen,
     * se rellena la tabla pasada por parametro.
     * @param tablaImagenes
     * @throws java.sql.SQLException
     * @throws java.io.IOException
     */
    public void LlenarTabla(JTable tablaImagenes) throws SQLException, IOException{
        DefaultTableModel modeloTabla = new DefaultTableModel() {
            @Override //Redefinimos el método getColumnClass
            public Class getColumnClass(int column){
                switch(column) {
                    case 0: return Object.class;
                    case 1: return Object.class;
                    case 2: return Object.class;
                    case 3: return ImageIcon.class;
                    default: return Object.class;
                }
            }
        };
        //Establecemos el modelo correspondiente en la JTable
        tablaImagenes.setModel(modeloTabla);
        
        //Añadimos las columnas correspondientes
        modeloTabla.addColumn("ID IMAGEN");
        modeloTabla.addColumn("ES CATEGORIA");
        modeloTabla.addColumn("DESCRIPCION");
        modeloTabla.addColumn("IMAGEN"); //Esta es la columna [3], es la que
                                         //nos interesa que sea una imagen.
                
        Object[] columna = new Object[4];
        
        ArrayList<imagen> listaImagenes = modeloImagenes.ListarImagenXEsCategoria("","");
        
        int numRegistros = listaImagenes.size();
        
        for (int i = 0; i < numRegistros; i++) {
            columna[0] = listaImagenes.get(i).getIdImagen();
            columna[1] = listaImagenes.get(i).getEsCategoria();
            columna[2] = listaImagenes.get(i).getDescripcion(); 

            //Transformamos el campo blob en ImageIcon
            Blob blob = listaImagenes.get(i).getImagen();
            int blobLength = (int) blob.length();  
            byte[] bytes = blob.getBytes(1, blobLength);
            blob.free();
            BufferedImage img = ImageIO.read(new ByteArrayInputStream(bytes));
            ImageIcon icon = new ImageIcon(img); 
            
            //Añadimos la imagen a la columna correspondiente
            columna[3] = icon;
            
            //Añadimos la fila al modelo
            modeloTabla.addRow(columna);
            
            //Establecemos el alto de la fila                                   
            tablaImagenes.setRowHeight(i, icon.getIconHeight());    
        }
        
   } 


No voy a entrar en el detalle de cómo recupero los datos de MySQL ni de cómo se define la clase Imagen (si queréis el código podéis pedírmelo en los comentarios y os lo facilitaré), pero sí quiero que prestéis atención a este código:

        DefaultTableModel modeloTabla = new DefaultTableModel() {
            @Override //Redefinimos el método getColumnClass
            public Class getColumnClass(int column){
                switch(column) {
                    case 0: return Object.class;
                    case 1: return Object.class;
                    case 2: return Object.class;
                    case 3: return ImageIcon.class;
                    default: return Object.class;
                }
            }
        };

Ese fragmento de código define el modelo que utilizará el objeto JTable y sobre el hemos de redefinir el método getColumnClass para que, en la columna [3] nos devuelva un ImageIcon, que es lo que queremos mostrar.

Otra parte importante del código, y que seguro que muchos ya conocéis, es el encargado de convertir el campo BLOB en un ImageIcon.
 
            //Transformamos el campo blob en ImageIcon
            Blob blob = listaImagenes.get(i).getImagen();
            int blobLength = (int) blob.length();  
            byte[] bytes = blob.getBytes(1, blobLength);
            blob.free();
            BufferedImage img = ImageIO.read(new ByteArrayInputStream(bytes));
            ImageIcon icon = new ImageIcon(img); 
            

Con estos sencillos pasos podemos obtener el resultado deseado.

Resultado final en una aplicación SWING

Si tienes cualquier duda o comentario recuerda que puedes exponerlo aquí o bien mediante nuestro twitter y facebook.
Compartir:

jueves, 16 de junio de 2016

Truco Delphi - Alternar colores de filas en DBGrid

Hoy os presento un pequeño truco que hará que vuestros DBGrids luzcan mucho mejor añadiendo unas pocas lineas de código.

Lo que tratamos de conseguir es que nuestro DBGrid presente las filas con colores alternos y además que la fila seleccionada se resalte también de manera alterna.


Para conseguir este objetivo debemos escribir la función GridDrawColumnCell como sigue:


procedure TfrmPrincipal.GridDrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
const
  RowColors: array[Boolean] of TColor = (clSilver, clWhite);
  RowSelectedColors: array[Boolean] of TColor = (clHotLight, clHighlight);
var
  OddRow: Boolean;
begin
  if (Sender is TDBGrid) then
  begin
    OddRow := Odd(TDBGrid(Sender).DataSource.DataSet.RecNo);
    if (gdSelected in State) then
      TDBGrid(Sender).Canvas.Brush.Color := RowSelectedColors[OddRow]
    else
      TDBGrid(Sender).Canvas.Brush.Color := RowColors[OddRow];
    TDBGrid(Sender).DefaultDrawColumnCell(Rect, DataCol, Column, State);
  end;
end;


Este procedimiento lo podemos poner en el formulario donde esté el DBGrid o bien en una unidad aparte y luego importarla con el comando Uses. Si incluimos el procedimiento en el formulario, es importante hacerlo como procedimiento de clase:

 TfrmPrincipal = class(TForm)

    { Otros métodos y propiedades del formulario }

    procedure GridDrawColumnCell(Sender: TObject; const Rect: TRect;
                                 DataCol: Integer; Column: TColumn; State: TGridDrawState);
  private
    { Private declarations }

  public
    { Public declarations }
  end;



De esta manera podremos seleccionar el DBGrid y asignar el procedimiento al evento OnDrawColumnCell.


Si tienes cualquier duda o comentario recuerda que puedes exponerlo aquí o bien mediante nuestro twitter y facebook.
Compartir:

miércoles, 15 de junio de 2016

Truco Delphi - Prevenir la ejecución de más de una instancia de nuestra aplicación (I)


Hace ya bastante tiempo que no posteo, pero eso no quiere decir que me haya olvidado de vosotros.
Como no dispongo de mucho tiempo para continuar con el curso de Lazarus y postear de forma asidua los artículos que tenía previstos, voy a empezar a postear pequeños tips y códigos de ejemplo para resolver pequeños problemas que me surgen en el día a día.

Hoy quiero mostraros como hacer que vuestra aplicación no se ejecute más de una vez, pero, en lugar de manteniendo la instancia más antigua, haciendo que la nueva instancia tome el control, es decir, que la nueva ejecución sustituya a la antigua.

Para ello nos vamos a basar en el procedimiento de WinApi GetCurrentProcessId, que nos dará el id de proceso del programa que estamos ejecutando y en el objeto TApplication para obtener el ExeName que será el que buscaremos.



Básicamente lo que pretendemos es terminar cualquier proceso que se llame como el nuestro, pero que no sea el nuestro :D


Añadimos el siguiente código en el evento OnCreate de nuestro formulario principal.

procedure TfrmPrincipal.FormCreate(Sender: TObject);
begin
  FProcessID := GetCurrentProcessId;
  FExeName   := ExtractFileName(Application.ExeName);
  
  CerrarInstancias;
end;

Este es el código que recorrerá todos los procesos de Windows y eliminará las instancias que existan de nuestra aplicación excepto la actual.

procedure TfrmPrincipal.CerrarInstancias;
const
  PROCESS_TERMINATE = $0001;
var
  ContinueLoop: BOOL;
  FSnapshotHandle: THandle;
  FProcessEntry32: TProcessEntry32;
begin
  FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
  ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);


  while Integer(ContinueLoop) <> 0 do
  begin

      if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) =
          UpperCase(FExeName)) or
          (UpperCase(FProcessEntry32.szExeFile) =
          UpperCase(FExeName)))  and
         (FProcessEntry32.th32ProcessID <> FProcessID)
      then
      begin
        TerminateProcess(OpenProcess(PROCESS_TERMINATE,
                                    BOOL(0),
                                    FProcessEntry32.th32ProcessID),
                                    0);
      end;

       ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
  end;
  CloseHandle(FSnapshotHandle);

end;

Mas adelante pondré otras maneras de prevenir la ejecución de más de una instancia de nuestras aplicaciones.
Compartir:

domingo, 3 de abril de 2016

Curso de Delphi - Capítulo 3. Variables y Constantes


Ya está aquí el tercer episodio de nuestro curso de Delphi sobre Lazarus.
En este tercer capítulo nos vamos a centrar en:

  • Tipos de datos básicos y derivados
  • Variables y constantes
  • Ámbito y compatibilidad
  • Operaciones disponibles

En este tema es especialmente importante entender correctamente el concepto de ámbito y la compatibilidad entre los distintos tipos de datos disponibles en Pascal.

Esperando que sea de vuestro total agrado os dejamos con el vídeo.

Compartir:

jueves, 31 de marzo de 2016

Hola Mundo multilingüe

¡Hola Mundo!

Aprovechando que he implementado SyntaxHighLighter en el blog, vamos a hacer un repaso por la mayoría de lenguajes de programación haciendo lo primero que debería hacer todo programador que empieza con un nuevo lenguaje de programación; el programa "Hola Mundo"

Espero que os guste el formato. A partir de ahora empezaré a incluir entradas con tips de programación en diferentes lenguaje y rutinas interesantes para que las tengamos todos a mano.

ColdFusion

<html>
<head>
<title>Test</title>
</head>
<body>

  <cfset message = "¡Hola Mundo!">
  <cfoutput>#message#</cfoutput>

</body>
</html>

C#

using System;
namespace HelloWorld
{
    class Hello 
    {
        static void Main() 
        {
            Console.WriteLine("¡Hola Mundo!");           
            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }
}

C++

#include <iostream>
 
int main()
{
  std::cout << "¡Hola Mundo!" << std::endl;
  return 0;
}

Delphi/Pascal

program Hello;
begin
  writeln ('¡Hola Mundo!');
  readln
end.

JavaScript

<!DOCTYPE HTML>
<html>
<body>

  <p>Header...</p>

  <script>
    alert('¡Hola Mundo!')
  </script>

  <p>...Footer</p>

</body>
</html>

Java
public class HelloWorld {

    public static void main(String[] args) {
        System.out.println("¡Hola Mundo!");
    }

}

Perl

  #!/usr/bin/env perl

  use v5.10.0;
  use warnings;
  use strict;

  say "¡Hola Mundo!";

Php

<html>
<head>
<title>Test</title>
</head>
<body>

 <?php
  $message = "¡Hola Mundo!";
  echo $message;
 ?>

</body>
</html>

PowerShell

$strString = "¡Hola Mundo!"
write-host $strString

Python

print("¡Hola Mundo!")

Ruby

puts '¡Hola Mundo!'

Visual Basic

Module Hello
  Sub Main()
      MsgBox("¡Hola Mundo!")  
  End Sub
End Module

Compartir:

lunes, 28 de marzo de 2016

Juegos para programar: Lightbot: Code Hour

Hace ya varias semanas desde la última entrada y varias más desde el primer artículo sobre "Juegos para programar". Lo cierto es que he estado bastante ocupado con el Master de Java, Semana Santa, Vacaciones, etc... pero aquí estamos de nuevo para volver a bloguear más a menudo.


LightBot: Code Hour

Hoy os traemos un juego que hará las delicias de los pequeños y no tan pequeños. Se llama LightBot: Code Hour. Este pequeño juego es gratuito y nos ofrece una secuencia de puzzles que irán creciendo en dificultad y que nos acercarán a temas tan propios de la programación como los procedimientos y los bucles.


¿En que consiste?

El juego consiste en dirigir nuestro LightBot hacia una serie de cuadrículas azules, distribuidas por un tablero, y encendiendo una bombilla sobre ellos. La gracia del asunto es que tenemos un número máximo de acciones que podemos llevar a cabo para acabar cada una de las fases.



Tendréis la posibilidad de seleccionar el idioma que queráis (entre ellos el español) y el género de vuestro LightBot.

El juego puede resultar algo corto, pero si tenemos en cuenta que es gratuito y a quién va dirigido, no me cabe duda de que será muy interesante para los más pequeños.



Otras versiones

Si os quedáis con ganas de más, tenéis disponibles dos versiones adicionales de LightBot, una de 4 a 8 años y otra para edades de 9 en adelante. Desafortunadamente estas versiones ya son de pago y su precio oscila entre los 2,99€ y los 3,18€ dependiendo de la versión y la plataforma.

Además tenéis una versión de navegador a la que podéis acceder desde aquí y jugar gratuitamente


Espero que os haya gustado este post y que me dejéis en los comentarios si queréis que hable sobre algún juego concreto que consideréis interesante para esta temática y lo incluiré sin problemas.

Compartir:

miércoles, 2 de marzo de 2016

Retrospectiva. Febrero 2016



Ya estamos en Marzo y, de la misma manera que el mes pasado y como haremos todos los meses, toca hacer una retrospectiva sobre el mes que acaba de pasar.

A veces las cosas no salen como uno quiere, unas veces debido a imprevistos y otras (la mayoría) por errores de estimación o planificación. Este mes en el blog hemos tenido un poco de todo: Por un lado, como algunos ya sabéis, estoy viviendo en Mallorca, pero mi familia está en Almería. Esto implica que, aproximadamente, cada dos semana estoy yendo a ver a mi mujer y a mis hijas, y este mes no había tenido en cuenta estos viajes para la planificación del blog. En realidad esto no supone ningún problema ya que he decidido tomarme este blog como lo que es, mi hobbie, así que no pienso agobiarme por no publicar un post durante la semana ni nada por el estilo. Por otro lado muchos que me seguís en las redes sociales sabréis que he empezado un curso experto de Java, (J2SE, J2EE y Android) y el tiempo que me va a consumir su realización.

En la retrospectiva de Enero os comentaba que intentaría subir a 9 los post durante este Febrero; esto no ha podido ser así debido a lo que os comentaba un poco más arriba. También quería seguir añadiendo mejoras al blog que han tenido que posponerse para este mes. Lo que si ha podido empezar es el curso de Delphi sobre Lazarus cuyos dos primeros capítulos tenéis aquí:


Esta misma semana tendréis el siguiente capítulo disponible. Si no queréis perderos nada os recomiendo que os suscribáis al canal de youtube así como al feed de este blog, pero eso ya es cosa vuestra (aunque os lo agradecería enormemente).

Para este mes de Marzo voy a ser bastante conservador en cuanto objetivos. Voy a plantearme hacer entre 7-9 entradas de las cuales 4 serán capítulos del curso de Delphi, de manera que me quede tiempo suficiente para continuar mi curso de Delphi. Incluiré las mejoras que tenía pensadas para Febrero y añadiré una página destinada a los cursos y otra destinada a una recopilación de blogs que suelo leer y que me parecen interesantes.

Sin más, me despido hasta el próximo post.


Code Safe…
Compartir:

domingo, 28 de febrero de 2016

Juegos para programar: Bit by Bit

Siempre he dicho que la programación es un ejercicio mental, independiente del lenguaje utilizado. Programar es el medio para resolver problemas utilizando un lenguaje de programación apropiado, por eso en la carrera de ingeniería informática se enseñan matemáticas, lógica, algorítmia, etc.

Creo que es de vital importancia, si sois padres, que enseñéis a vuestros hijos/as a pensar por si mismos, a sacar conclusiones, deducir, planificar y ejecutar. Hay muchas maneras de hacerlo: juegos de estrategia como el ajedrez o juegos de construcción tipo Lego, Tente, Megablocks, son un buen ejemplo. Estos juegos ayudan a los más pequeños a desarrollar su inteligencia visio-espacial y deductiva.

Hoy en día con la tecnología disponible, son muchas las opciones que tenemos al alcance de la mano. Con esta serie de entradas semanales pretendo acercaros los juegos y aplicaciones, tanto para Android como para PC/navegador que considero interesantes para el desarrollo de los más pequeños. Recordad que siempre es recomendable estar con ellos mientras usan cualquier dispositivo conectado a internet, de forma que vosotros los controléis en todo momento y de esa manera, además, compartáis un buen rato jugando, aunque sea con una "maquinita".


Bit by Bit: Programming game:


El juego que os quiero presentar hoy es Bit by Bit: Programming game. Podréis encontrarlo en Play Store y la mecánica es tan simple que os sorprenderá. Se trata de una serie de puzzles predefinidos que tenemos que ir resolviendo para poder pasar de nivel. Para la resolución de estos puzzles tendremos que utilizar distintos objetos (serán diferentes para cada nivel) para llevar a los Bits de diferentes colores a su correspondiente destino. 



Parece fácil ¿no?. De hecho lo es. Aunque se irá complicando con el paso de los niveles, la curva es bastante aceptable, y niños a partir de 5-6 años no encontrarán demasiados problemas en resolver los primeros niveles una vez hayan aprendido la mecánica.


¿Por que es interesante este juego?


Este juego ha sido desarrollado con ayuda de niños, padres y especialistas en educación y, mientras juegan, los más peques aprenderán cosas como:
  • Planificación
  • Creatividad en la resolución de problemas
  • Pensamiento analítico y lógico
Os recomiendo que lo probéis, os va a gustar. Solamente tiene una pega que comprobaréis después de la primera partida, la publicidad. Después de cada nivel el juego nos mostrará un vídeo publicitario bastante molesto. La manera de evitar esto es activando el modo avión y dejando nuestro dispositivo completamente offline

Me sorprende las pocas descargas que tiene este juego y creo que es debido a una mala campaña de marqueting. Imagino que con el tiempo añadirán mas niveles y pondrán la opción de comprarlo para no tener esa molesta publicidad, siempre y cuando tengan descargas suficientes.



Si conocéis juegos de estas características y queréis compartirlos, podéis dejarme vuestros comentarios debajo del post o directamente mencionándome en mi cuenta de twitter y los tendré en cuenta para futuros posts.
Compartir:

domingo, 21 de febrero de 2016

Curso de Delphi - Capítulo 2. Primera aplicación



Ya ha pasado una semana desde que publiqué el primer episodio de nuestro curso de Delphi sobre Lazarus y hoy toca que avancemos un poco.

En este capítulo trataremos los siguientes temas:

  • El IDE de Lazarus.
  • Proyectos en Delphi.
  • Componentes, métodos y eventos.
  • Nuestro primer programa.

Espero que os guste y que os suscribáis al canal. Un saludo!

Compartir:

viernes, 19 de febrero de 2016

Historia del ratón (Mouse)

Mucho ha llovido desde los tiempos en los que teníamos que limpiar los rodillos de nuestro ratón, lustrar la bola y limpiar la alfombrilla. Muchos pensaréis que la historia del ratón empieza con esos dispositivos toscos, con 2 botones (en el mejor de los casos) y cuya precisión dependía, en gran medida, de lo limpias que mantuvieras tu mesa y tus manos, pero hay mucho más.

Un poco de historia.



El X-Y Position Indicator for a Display System (nombre inicial del dispositivo) fue diseñado por Douglas Engelbart y Bill English en el Stanford Research Institute (universidad de Stanford) durante los años 60. 

Fue el 9 de diciembre de 1968 donde se presentó el primer modelo oficial al público en San Francisco. Esta presentación, que duró hora y media, mostraba entornos gráficos con sistemas de ventanas y como mover el cursor mediante el PIDS para interactuar con ellas.

A pesar de lo revolucionario del dispositivo, la informática del momento no estaba preparada para adoptar un dispositivo como ese. No fue hasta el 27 de abril de 1981 cuando se lanzó la Xerox Star 8010, una potente estación de trabajo que incluía una interfaz gráfica que dependía enteramente de este dispositivo. Aunque era un avance el dispositivo seguía siendo muy caro. Una versión 2 años después por parte de Microsoft, con un precio de 195 dolares, pasó totalmente desapercibida.

Si el ratón estaba destinado a ser un periférico disponible en cada hogar, debía costar entre los 10 y los 35 dólares. Eso fue lo que pensó Steve Jobs cuando pidió a un grupo de jóvenes el desarrollo de un periférico, fiable, barato y cuya producción pudiera realizarse en serie. En 1984 apareció la computadora Macintosh que sería la llamada a popularizar este periférico que nos recordaba a todos a un ratón.

Ratón Macintosh

El funcionamiento.


Aunque los ratones han evolucionado muchísimo desde sus primeras versiones de bola (mecánicos), la esencia sigue siendo la misma. El dispositivo debe capturar y transmitir los movimientos del usuario al ordenador para reflejar este movimiento en la pantalla. Una vez metidos en materia nos encontramos ratones de bola, opticos y laser en su versión wired (con cable) o wireless, gaming o de oficina, de gama alta o de gama baja. Los hay para todos los gustos y colores.

No voy a entrar en mucho detalle sobre como funciona un ratón internamente, pero para los más curiosos os dejo un vídeo que os explicará el funcionamiento de un ratón laser.




Los incomprendidos.


Lo cierto es que no sabía muy bien como titular a esta sección. La iba a llamar "Los grandes fiascos", pero eso sería ser demasiado cruel y quizás injusto; creo que incomprendidos define mucho mejor a los dispositivos o sistemas que voy a mencionar a continuación.

Hemos hablado de que hay dispositivos wired o wireless, pues bien, no se si sabéis (quizá alguno incluso lo haya tenido en sus tiempos de 386 o 486) que había ratones wireless por infrarrojos. Por suerte para nosotros en los años siguientes se desarrollo la conexión por radiofrecuencia y más adelante la bluetooth (aunque esta no es que esté demasiado extendida), pero a lo que vamos; imaginaros lo que era tener que estar constantemente pendiente de donde estaba la base receptora para que el ratón no perdiese la conexión... era un infierno.

Raton Cordless Infrarrojo JVC


Otro de los incomprendidos, aunque se utiliza bastante en la navegación marítima es el trackball. Este dispositivo, a diferencia del ratón convencional, tiene la bola en la parte superior de tal manera que el usuario puede moverla en lugar de tener que desplazar el dispositivo por una superficie. Es ideal si no disponemos de demasiado espacio pero es bastante incomodo de utilizar si ya te has acostumbrado a un ratón convencional.

TrackBall


El futuro.


Como se suele decir, el futuro ya está aquí. Lo vemos a diario con nuevos modelos con más funciones, con baterías que duran hasta 3 años como el caso del Dendro de Hiditec (el ratón detecta cuando el usuario posa la mano encima para activarse); ratones como el Magic Mouse de Apple, que carece de botones, o auténticas monstruosidades gaming como el Saitek.

Ratón MadCatz SayTek

Si me preguntáis a mi cual creo que será el futuro de estos dispositivos os lo diré claramente... desaparecer, no será hoy ni mañana, pero estamos viendo una tendencia muy fuerte hacia lo táctil y hacia lo virtual. Ya hay dispositivos como el TrackIR que detectan el movimiento de la cabeza y que permiten una inmersión total en videojuegos de simulación. Yo creo que el futuro pasa por un dispositivo que nos permita tener la mano libre, de forma que simplemente con el movimiento de la cabeza, ojos o, quien sabe, incluso pensamiento, permita interactuar con nuestros ordenadores de la misma manera, o mejor, que lo hacemos hoy en día.

Os dejo con un vídeo sobre que es y como funciona el TrackIR para que os hagáis una idea de lo que viene.



"La tecnología es sólo una herramienta. En términos de llevar a los niños a trabajar juntos y motivarlos, el profesor es el más importante."
Bill Gates


Compartir:

Stream

Con la tecnología de Blogger.

BoosterBlog

BoosterBlog
BoosterBlog

Timeline Twitter

Seguidores

Seguidores