El patrón de desbloqueo es una medida de seguridad que tienen algunos teléfonos inteligentes para evitar el acceso al dispositivo por parte de personas extrañas, este patrón consiste por lo general en una matriz 3×3 de círculos o puntos los cuales se unen con el dedo para formar el «patrón de desbloqueo«, si el patrón es correcto, se tiene acceso al dispositivo móvil, caso contrario este continuara boqueado.
Pues bien, esta manera de evitar el acceso de personas no autorizadas a un dispositivo móvil puede extrapolarse a una aplicación de escritorio e incluso porque no, a una aplicación web.
Herramientas
Tiempo: 20 minutos
Nivel: Intermedio – Avanzado
Paso 1. Análisis y diseño
Este sistema de bloqueo esta formado por un panel con una matriz 3×3 de figuras circulares que permiten dibujar el patrón de desbloqueo.
Cada uno de estas figuras tiene asignado un valor que debe ser único, en nuestro ejemplo valores del 1 al 9, son estos valores los que forman el patrón de desbloqueo. Cuando el usuario arrastra el dedo entre cada uno de estas figuras, internamente se va formando un código, es decir, en la imagen de abajo podemos advertir que según el movimiento que se le de al sistema, se forma un código «125895«, el código de desbloqueo del ejemplo de este post.
Cada elemento de la matriz es un objeto de 80×80 pixeles el cual esta conformado por un circulo externo y un circulo más pequeño en su centro, las medidas y coordenadas de cada objeto se pueden ver a continuación
Paso 2. El Proyecto
Crea un nuevo proyecto java con nombre «Unlock Pattern«, agrega la siguiente estructura:
El proyecto contiene 2 paquetes :
El paquete unlockpattern esta formado por las siguientes clases:
Adicionalmente hacemos uso de una imagen, no es necesaria ya que podíamos pintar su contenido directamente con java2d pero a veces la flojera nos gana 🙂 la imagen que utilizaremos esta en formato PNG de 290×93 pixeles, la imagen es la siguiente:
Paso 3. FigurePattern
Como dijimos más arriba esta clase nos pintara un par de figuras circulares a modo de botón en nuestro sistema de desbloqueo, las medidas de esta figura se indican en el paso 1, el código de la clase es:
package net.jc_mouse.unlockpattern; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; import java.awt.geom.Ellipse2D; /** * @web https://www.jc-mouse.net/ * @author Mouse */ public class FigurePattern { //identificador/valor de objeto (NO debe repetirse) private int key; //coordenadas private int x = 0; private int y = 0; //bandera private boolean selected = false; //area sensible a eventos del raton private Rectangle area = new Rectangle(); /**Constructor de clase */ public FigurePattern(){} /** * Constructor de clase * @param k clave de celda * @param x coordenada X de objeto * @param y coordenada Y de objeto */ public FigurePattern(int k, int x, int y){ this.key = k; this.x = x; this.y = y; //area interna del circulo area.setBounds(x+10, y+10 , 60, 60); } public void draw(Graphics2D g2){ //fondo g2.setColor( new Color(0,0,0) ); g2.fill( new Ellipse2D.Double(x+10, y+10 , 60, 60 ) ); //borde exterior g2.setStroke(new BasicStroke( 4 )); g2.setColor( (selected)?new Color(0,204,0):new Color(153,153,153) ); g2.draw( new Ellipse2D.Double(x+10, y+10 , 60, 60 ) ); //circulo interno g2.setColor( new Color(255,255,255) ); g2.fill( new Ellipse2D.Double(x+30, y+30 , 20, 20 ) ); } public int getKey() { return key; } public void setKey(int key) { this.key = key; } public boolean isSelected() { return selected; } public void setSelected(boolean selected) { this.selected = selected; } public Rectangle getArea() { return area; } public void setArea(Rectangle area) { this.area = area; } /** * retorna el punto medio de la figura * @return Point */ public Point getCenterPoint(){ Point p = new Point( x+40, y+40); return p; } /** * Metodo statico que determina su un punto se encuentra dentro un area rectangular * @param r rectangle * @param p point * @return boolean */ public static boolean insideArea(Rectangle r,Point p) { return r.contains(p); } }//end:FigurePattern
Paso 4. UnlockPanel
Esta clase que desciende de un JPanel sera donde se pinte la matriz con las 9 figuras circulares, así mismo implementa métodos para que el usuario pueda arrastrando el cursor del mouse dibujar el patrón de desbloqueo .
El método checkUnlockPattern() se encarga de verificar si el patrón introducido por el usuario es correcto,de ser cierto, abrirá un nuevo JFrame (tu aplicación) que en nuestro ejemplo se encuentra en el paquete «demo» y se llama «AppDemoJFrame«, caso contrario, de ser un patrón incorrecto, muestra un mensaje de error «Access denied».
package net.jc_mouse.unlockpattern; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Point; import java.awt.RenderingHints; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.geom.Rectangle2D; import java.util.ArrayList; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JPanel; import net.jc_mouse.demo.AppDemoJFrame; /** * @web https://www.jc-mouse.net/ * @author Mouse */ public class UnlockPanel extends JPanel implements MouseListener,MouseMotionListener { private JFrame parent; private String myKey="125895";//patron de desbloqueo //array para las 9 figuras que forman la matriz private ArrayList<FigurePattern> figurePatternArr = new ArrayList(); //array para las figuras que conforman el patron desbloqueo private ArrayList<FigurePattern> pattern= new ArrayList(); //String para guardar el patron generado por el usuario private String password = ""; //para mostrar imagen de "acceso denegado" private final Image image = new ImageIcon(getClass().getResource("/net/jc_mouse/unlockpattern/access_denied.png")).getImage(); private boolean showError=false; /** * Constructor de clas * @param parent JFrame que contiene el JPanel */ public UnlockPanel(JFrame parent){ this.parent = parent; //se agregan 9 circulos al contenedor figurePatternArr.add(new FigurePattern(1,0,0)); figurePatternArr.add(new FigurePattern(2,80,0)); figurePatternArr.add(new FigurePattern(3,160,0)); figurePatternArr.add(new FigurePattern(4,0,80)); figurePatternArr.add(new FigurePattern(5,80,80)); figurePatternArr.add(new FigurePattern(6,160,80)); figurePatternArr.add(new FigurePattern(7,0,160)); figurePatternArr.add(new FigurePattern(8,80,160)); figurePatternArr.add(new FigurePattern(9,160,160)); //Eventos del raton UnlockPanel.this.addMouseListener( UnlockPanel.this ); UnlockPanel.this.addMouseMotionListener( UnlockPanel.this); } @Override public void paintComponent(Graphics g){ Graphics2D g2 =(Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); g2.setColor( new Color(0,0,0) ); g2.fill(new Rectangle2D.Double(0,0,getWidth(),getHeight())); //dibuja las lineas del patron de desbloqueo entre los circulos Point point = null; for(FigurePattern figurePattern: pattern){ g2.setStroke( new BasicStroke( 20 ) ); g2.setColor( new Color(204,204,204) ); if(point!=null) g2.drawLine(point.x, point.y, figurePattern.getCenterPoint().x, figurePattern.getCenterPoint().y); point = figurePattern.getCenterPoint(); } //dibuja los circulos para los patrones de desbloqueo if(figurePatternArr!=null) figurePatternArr.stream().forEach((b) -> { b.draw(g2); }); //muestra error if(showError){ g2.drawImage(image, (getWidth()-220)/2, (getHeight()-93)/2, 220, 93, null); } } @Override public void mouseClicked(MouseEvent e) {} @Override public void mousePressed(MouseEvent e) {} @Override public void mouseReleased(MouseEvent e) { checkUnlockPattern(); } @Override public void mouseEntered(MouseEvent e) {} @Override public void mouseExited(MouseEvent e) {} @Override public void mouseDragged(MouseEvent e) { //cuando se arrastra el cursor del mouse figurePatternArr.stream().filter((p) -> ( FigurePattern.insideArea(p.getArea(),e.getPoint()) )).forEach((p) -> { if(this.pattern.isEmpty()){//Si esta vacio se añade objeto pattern.add(p);//añade a array p.setSelected(true);//cambia color password +=p.getKey();//concatena valor de figura }else{//Si ya existen objetos en el array //se comprueba que objeto nuevo no se repita con el ultimo añadido if(pattern.get(pattern.size()-1).getKey() != p.getKey()){ pattern.add(p);//añade a array p.setSelected(true);//cambia color password +=p.getKey(); //concatena valor de figura } } }); repaint(); } @Override public void mouseMoved(MouseEvent e) { showError=false; repaint();} /** * metodo para comprobar que patron de desbloqueo es correcto * de ser asi -> abre nuevo formulario * caso contrario -> muestra mensaje de error */ public void checkUnlockPattern(){ if(password.equals(myKey)){//si patron de desbloqueo es correcto parent.setVisible(false);//se oculta //se muestra aplicacion cliente AppDemoJFrame app = new AppDemoJFrame(); app.setVisible(true); }else{ showError=true; } pattern.clear();//limpia movimientos antiguos password="";//resetea password //reinicia valor para objetos figurePatternArr.stream().forEach((b) -> { b.setSelected(false); }); repaint(); } }//end
Paso 5. UnlockJFrame
Para terminar el tutorial, el panel creado en el paso 4, debemos añadirlo a un JFrame para poder ejecutarlo, la clase queda de la siguiente forma:
package net.jc_mouse.unlockpattern; import java.awt.Dimension; import java.awt.EventQueue; import javax.swing.JFrame; import javax.swing.WindowConstants; /** * @web https://www.jc-mouse.net/ * @author Mouse */ public class UnlockJFrame extends JFrame { private UnlockPanel unlockPanel; /**Constructor de clase*/ public UnlockJFrame(){ initComponents(); UnlockJFrame.this.setLocationRelativeTo(null); } private void initComponents() { setTitle("Unlock Pattern"); setResizable(false); setSize(new Dimension(246,280)); setPreferredSize(new Dimension(246,280)); unlockPanel = new UnlockPanel(this); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); getContentPane().add(unlockPanel); pack(); } public static void main(String args[]){ EventQueue.invokeLater(() -> { new UnlockJFrame().setVisible(true); }); } }
Ejecutamos y probamos, no olvides el patrón de desbloqueo es «125895»
Código fuente: <<enlace pobre>>
enjoy!!!
En este tutorial crearemos una aplicación android que nos permitirá abrir un PopupMenu de donde podremos seleccionar una[...]
Cuando se realizan aplicaciones en java con base de datos y se llega a un punto donde es necesario realizar una consulta[...]
Microsoft acaba de lanzar Cascadia Code una fuente monoespaciada enfocada en proporcionar una mejor experiencia en conso[...]
En este tutorial conoceremos una forma de conectar una aplicación en Laravel con tres bases de datos diferentes, 2 en My[...]
PROBLEMA: Se tiene un JTable con 19 columnas y 50 registros, se desea personalizar el JTable de la siguiente manera:[...]
La internacionalización permite a las aplicaciones adaptarse a los diferentes idiomas y regiones sin necesidad de cambio[...]