Java Swing 8: El JTree

2013-01-28 - Categorías: Java / Java Swing
Volviendo de nuevo con un nuevo post sobre Swing, esta vez os dejo un componente un poco más complicado de entender, el JTree. Su uso con el Swing Designer es bien simple de ponerlo en un frame y dibujar su interfaz, pero cuando entremos en su estructura que tenemos para manejarlo necesitaremos tener conocimientos de lo que es un Tipo Abstracto de Datos (TAD para los amigos), y en concreto lo que es un árbol. Lo que se puede hacer y cómo se estructura internamente lo supongo por entendido. Si no es el caso mejor empezar por ver ésto, sino lo de a continuación puede convertirse en un jeroglífico.

http://es.wikipedia.org/wiki/Tipo_de_dato_abstracto
Búsqueda en Google sobre TADs árboles

Construyendo el escenario

Para éste tutorial he utilizado Eclipse Juno y la versión 7 update 9 del JDK. Lo primero es crear, dentro de Eclipse, en la ventana del explorador de proyectos, un nuevo proyecto de Java. Luego crear un nuevo JFrame con el asistente de Eclipse y ya tenemos el esqueleto del programa listo para empezar. Yendo al diseñador de formularios del Swing Designer le añades un Absolute layout al formulario para poder posicionar los componentes donde quieras del formulario, y entonces para éste ejemplo le he añadido dos botón y un componente JTree. El componente JTree está a su vez dentro de un JScrollPane para que se muestren las barras de scroll si el contenido es más grande que lo que se puede ver. 
Antes de continuar te debe de haber quedado una ventana parecida a la de la imagen de inicio.
En la versión que tengo, cuando añado el JTree al Frame, se crea con un contenido sobre colores, deportes y comida. Éstos datos están en la propiedad model. De igual manera que algunos otros componentes, tenemos un modelo de árbol para usar el JTree. Por ejemplo, cuando usamos las listas tenemos modelos de listas, pues ahora son modelos de árbol. Si no establecemos el modelo, por defecto se construye con los elementos dichos. Vamos ahora con el TreeModel.

Creando el árbol

Vamos a usar dos tipos de datos para crear la estructura y ponerla en el JTree: el DefaultTreeModel y el  DefaultMutableTreeNode.
El botón para cargar el árbol lo he puesto para leer el árbol de directorios de tu disco duro. El tipo de datos TreeModel es el objeto que tiene internamente el JTree para manejar su estructura en árbol, nosotros vamos a usar una clase derivada de ésta porque se trata de una interfaz que no podemos usar directamente. Entonces tenemos el DefaultTreeModel que va a ser el tipo que usaremos.
Por otro lado tenemos que en cada elemento de un DefaultTreeModel es un DefaultMutableTreeNode. De forma que cada nodo de éstos puede tener a su vez hijos, formando así un árbol según tenga hijos o no. Para entenderlo ésto he pensado usar el árbol de directorio que todos conocemos.
Antes de seguir, explicando las dos funciones del JTree, si queremos crear una estructura de tipo árbol como por ejemplo:

nodoroot
– nodo1 (indice 0)
— nodo1.1 (indice 0)
— nodo1.2 (indice 1)
– nodo2 (indice 1)
— nodo2.1 (indice 0)
—  nodo2.2 (indice 1)

…lo que tenemos que hacer es que cada nodo es un elemento de tipo DefaultMutableTreeNode, y cada elemento se puede hacer hijo de otro. Es decir, lo único que hay que decirle al programa es de cada nodo cuál es su padre con la función insertNodeInto(nodo, padre, índice). Por ejemplo para la estructura anterior programaríamos:
DefaultMutableTreeNode nodoroot, nodo1, nodo11, nodo12, nodo2, nodo21, nodo22;
nodoroot = new DefaultMutableTreeNode("Éste es el nodo principal.");
nodo1 = new DefaultMutableTreeNode("nodo1");
nodo11 = new DefaultMutableTreeNode("nodo11");
nodo12 = new DefaultMutableTreeNode("nodo12");
nodo2 = new DefaultMutableTreeNode("nodo2");
nodo21 = new DefaultMutableTreeNode("nodo21");
nodo22 = new DefaultMutableTreeNode("nodo22");
arbol.setRoot(nodoroot);
arbol.insertNodeInto(nodo1, nodoroot, 0);
arbol.insertNodeInto(nodo2, nodoroot, 1);
arbol.insertNodeInto(nodo11, nodo1, 0);
arbol.insertNodeInto(nodo12, nodo1, 1);
arbol.insertNodeInto(nodo21, nodo2, 0);
arbol.insertNodeInto(nodo22, nodo2, 1);
En el ejemplo os he dejado algo más complicado, con una función recursiva que carga toda la estructura de directorios desde el directorio raiz «/». Es decir, cuando le damos al botón tenemos el código siguiente:
btnCargarrbolDe.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {

DefaultTreeModel arbol = (DefaultTreeModel) tree.getModel();
DefaultMutableTreeNode nroot = new DefaultMutableTreeNode("Árbol de directorios");

arbol.setRoot(nroot);

CargaEstructuraDirectorios(arbol, nroot, "/");
}
});
… una vez dicho cual es el nodo principal (nroot), la función CargaEstructuraDirectorios lo hace todo. Puede tardar bastante, depende lo que tengas en tu ordenador o lo rápido que sea, déjalo ejecutarse hasta el final si lo quieres ver el resultado.
No voy a entrar en detalle sobre funciones recursivas o lectura de directorios. Lo que hay que saber es que lista un directorio, añadiendo todo lo que encuentra al árbol en su lugar adecuado, de maner que si encuentra un directorio lo añade también. Y acto seguido entra al directorio y lo lista, de manera que si algo de dentro también es un directorio vuelve a hacer lo mismo, es decir, vuelve a entrar en éste segundo directorio y lo lista también añadiendo de nuevo los elementos en el lugar adecuado. Así sucesivamente hasta listar todos los directorios y subdirectorios.
Todo ésto queda simple con una función recursiva que os dejo aquí:
private void CargaEstructuraDirectorios(DefaultTreeModel arbol, DefaultMutableTreeNode padre, String ruta) {
DefaultMutableTreeNode aux = null;

File archivo = new File(ruta);
File[] archivos = archivo.listFiles();

if (archivos != null) {
for (int i = 0; i < archivos.length; i++) {

aux = new DefaultMutableTreeNode(archivos[i].getName());
arbol.insertNodeInto(aux, padre, i);

if (archivos[i].isDirectory()) {
try {
CargaEstructuraDirectorios(arbol, aux, archivos[i].getAbsolutePath() + "/");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}

}

}
}

Borrar un nodo

Igual que se añaden nodos, también se pueden borrar. Usando la función removeNodeFromParent que se usa en el ejemplo. Con un botón simple. No sólo podemos borrar un nodo, también podemos borrarlo de un sitio y ponerlo en otro, reordenando nuestro árbol, modificándolo, o lo que necesitemos. Pero con añadir o borrar tenemos lo básico para empezar…

Click, empieza el juego

Ahora se complica, pero empieza el juego xD ¿cómo hacer algo cuando hacemos click en un elemento del árbol? Haciendo click derecho con el ratón en el JTree añadimos el capturador de eventos que vamos a usar para hacer álgo cuando el usuario hace click en el JTree:
Eclipse, de nuevo nos genera el código esqueleto siguiente:
final JTree tree = new JTree();
tree.addTreeSelectionListener(new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode nseleccionado = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
JOptionPane.showMessageDialog(frame, nseleccionado.getPath());
}
});
Se pueden capturar otros eventos. Y bueno, ya la imaginación o lo que necesitemos entra en juego para desarrollar lo que necesitemos. Con las funciones principales que nos proporcina el DefaultMutableTreeNode pordemos hacer lo que queramos. Podemos tener varios árboles y ponerlos en el JTree cuando queramos uno u otro, podemos recorrer los nodos por los índices, podemos saber cuál es el nodo principal con la función .getRoot, saber cuántos hijos tiene un nodo con .getChildCount, etcétera…
No hay más que curiosear para qué sirven las funciones proporcionadas, como podemos ver en la imagen siguiente del Eclipse:
Hay que saber que cuando hacemos cambios en la estructura de árbol, éstos automáticamente se visualizan en el JTree, con lo que sólo tenemos que centrarnos en el árbol.
Para más información me remito de nuevo a la documentación oficial:

Códigos del ejemplo

En el ejemplo he comentado algunas cosas más. Aquí están en descarga directa los códigos fuentes. Hay un .jar, para ejecutarlo necesitas el JRE instalado, si quieres modificarlo, sólo necesitas un editor de texto ya que sólo hay un fichero .java y recompilarlo.
Todo el código comentado es el siguiente para el que no quiera descargarlo:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.event.TreeModelListener;
import javax.swing.JButton;
import javax.swing.JTree;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.File;
import javax.swing.JScrollPane;
import javax.swing.event.TreeSelectionListener;
import javax.swing.event.TreeSelectionEvent;

// La clase principal
public class Principal extends JFrame {

// el panel contenedor
private JPanel contentPane;
// el JFrame
static Principal frame;

/**
* esta es la función que primero se ejecuta creando el JFRame y visualizándolo
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
frame = new Principal();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}

/**
* la creación del JFrame principal donde está programado todo lo de éste ejemplo
*/
public Principal() {
// título de ventana
setTitle("Java Swing 8 El JTree by Jnj");
// operación al cerra el JFrame
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// dimensiones y posición en el escritorio
setBounds(100, 100, 450, 306);
// se crea el panel
contentPane = new JPanel();
// los bordes
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
// se establece
setContentPane(contentPane);
contentPane.setLayout(null);

// se pone el botón en la ventana
JButton btnCargarrbolDe = new JButton(
"Cargar u00E1rbol de directorios");
btnCargarrbolDe.setBounds(10, 11, 200, 23);
contentPane.add(btnCargarrbolDe);

// las barras de escroll para el JTree
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(10, 45, 414, 206);
contentPane.add(scrollPane);

// el JTree
final JTree tree = new JTree();
// que captura el evento click
tree.addTreeSelectionListener(new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent e) {
// se obtiene el nodo seleccionado
DefaultMutableTreeNode nseleccionado = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
// visualiza el path del nodo
JOptionPane.showMessageDialog(frame, nseleccionado.getPath());
}
});
// se pone el árbol en el panel de las barras de scroll
scrollPane.setViewportView(tree);

// aquí el botón que borra el último elemento de los primeros hijos
// es decir, desde el nodo root, borra sólo el último hijo
JButton btnBorrarltimoNodo = new JButton("Borrar u00FAltimo nodo");
btnBorrarltimoNodo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {

DefaultTreeModel arbol = (DefaultTreeModel) tree.getModel();
DefaultMutableTreeNode padre = (DefaultMutableTreeNode) arbol.getRoot();
int numeroDeHijos = arbol.getChildCount(padre);

// borra el último hijo del padre
arbol.removeNodeFromParent((MutableTreeNode) arbol.getChild(
padre, numeroDeHijos - 1));
}
});
btnBorrarltimoNodo.setBounds(220, 11, 204, 23);
contentPane.add(btnBorrarltimoNodo);

// evento click del botón de carga del árbol
// simplemente añade el nodo root y llama a la función de carga
// para añadir todos los nodos hijos al nodo root
btnCargarrbolDe.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {

DefaultTreeModel arbol = (DefaultTreeModel) tree.getModel();
DefaultMutableTreeNode nroot = new DefaultMutableTreeNode(
"Árbol de directorios");

arbol.setRoot(nroot);

CargaEstructuraDirectorios(arbol, nroot, "/");

}
});


}

// función recursiva que lista todos los directorios y subdirectorios
// a partir de una ruta, añadiéndolos a la estructura en árbol
private void CargaEstructuraDirectorios(DefaultTreeModel arbol,
DefaultMutableTreeNode padre, String ruta) {
DefaultMutableTreeNode aux = null;

File archivo = new File(ruta); // puntero al directorio de la ruta
File[] archivos = archivo.listFiles(); // lista todos los archivos de la ruta

// recorre lo que hay en la ruta
if (archivos != null) {
for (int i = 0; i < archivos.length; i++) {

// creando un nodo con cada cosa del directorio
aux = new DefaultMutableTreeNode(archivos[i].getName());
// inserta el nodo hijo
arbol.insertNodeInto(aux, padre, i);

// si encontramos un directorio volvemos a hacer lo mismo con sus hijos
if (archivos[i].isDirectory()) {
try {

// llamando recursivamente de nuevo a ésta misma función
CargaEstructuraDirectorios(arbol, aux,
archivos[i].getAbsolutePath() + "/");

} catch (Exception e) {
System.out.println(e.getMessage()); // por si acaso le he puesto un try xD
}
}

}

}
}

// termina la creación del frame
}

// fin de la clase

Un saludo.


Java Swing 7: Formateando textos

2013-01-18 - Categorías: Java / Java Swing

¡Hola de nuevo!

El tiempo pasa y no vuelve, el valor más preciado que tenemos, cuando a uno le falta es cuando lo tiene en cuenta. Estoy sacando tiempo de debajo de las piedras para seguir escribiéndoles. Vienen días de tormenta, hace mucho viento, parece que llueve pero no llueve, la prima de riesgo sube y baja, los políticos siguen con sus historias, y yo sigo con lo mío, así que aquí hoy os dejo algo más sobre Swing. En concreto sobre componentes para dar formato a textos y algo más.

En éste minitutorial, voy a dar un repaso a los componentes que sólo admiten cierto tipo de valores como los JFormattedTextField. Otro componente interesante, el JEditorPane, que admite por defecto tres tipos de contenido: el texto plano normal y corriente de siempre (text/plain), texto enriquecido (text/rtf), o un documento en HTML (text/html). Y otra caja de texto, el JTextPane, que admite incluso otros componentes Swing como etiquetas, botones, etcétera…

Para éste post he utilizado la versión JDK 7 update 9, y Eclipse Juno EE con el plugin Swing Designer.

JFormattedTextField

Éste componente hereda del JTextField, con lo que tiene los mismos métodos y se usa de manera parecida. La diferencia que tiene con respecto a los demás componentes de texto es que permite establecer una máscara de entrada para los datos que el usuario escribe. Por ejemplo si queremos poner un código postal, un número de teléfono, etcétera..
Éste componente es uno de los más prácticos porque bien programado nos aseguramos de que el usuario va a poner lo que queremos que ponga. La carencia que tiene es que no admite expresiones regulares directamente, pero se puede sortear éste problema.

En el ejemplo, tenemos el siguiente código:

JFormattedTextField formattedTextField =
new JFormattedTextField(new MaskFormatter("(####)#########"));
formattedTextField.setBounds(10, 36, 481, 20);
contentPane.add(formattedTextField);
Al constructor de JFormattedTextField, se le pasa un objeto nuevo de tipo MaskFormatter, y éste se encarga de usar la máscara de entrada para admitir o no los valores de entrada.

Podemos usar en la máscara los siguientes caracteres para contruir nuestra máscara:

#  cualquier número.
‘   carácter especial.
U carácter, que lo modifica a mayúsculas.
L  carácter, que lo modifica a minúsculas.
A  carácter o número.
?  cualquier carácter.
*  cualquier cosa.
H cualquier caracter hexadecimal, es decir, del 0 al 9 y de la ‘a’ a la ‘f’ o de la ‘A’ a la ‘F’.

También podemos comprobar con una expresión regular si el valor introducido es correcto. Tenemos un ejemplo programado, creando un objeto nuevo de tipo RegexFormatter aquí:
http://www.java2s.com/Tutorial/Java/0240__Swing/RegexFormatterwithaJFormattedTextField.htm
Si quieres construir el tuyo propio lo que debes hacer es siguiendo el siguiente código reprogramar el método stringToValue, comprobando que el texto de entrada es válido:
JFormattedTextField formattedTextField = 
new JFormattedTextField(new AbstractFormatter() {
@Override
public String valueToString(Object value) throws ParseException {
// TODO Auto-generated method stub
return null;
}

@Override
public Object stringToValue(String text) throws ParseException {
// TODO Auto-generated method stub
return null;
}
});
formattedTextField.setBounds(10, 36, 481, 20);
contentPane.add(formattedTextField);
Si quieres generar con Eclipse el código esqueleto, cuando llegues a donde pone new Abstract… le das a Ctrl + Espacio y te saldrán las opciones que tienes, ésto lo puedes hacer mientras que escribes en cualquier parte del programa para ir más rápido, entonces eliges dándole a Enter y te genera el código de aquí arriba. Ya con ésto puedes usar una expresión regular usando un ‘matcher’. Pero ésto ya sería para otro post.

Hay más de información en la documentación oficial.

JEditorPane

Éste componente admite tres tipos de textos formateados por defecto: texto plano, documento enriquecido RTF y HTML. Un ejemplo de uso es el siguiente:
JEditorPane editorPane = new JEditorPane();
editorPane.setContentType("text/html");
editorPane.setText("<h1>Título</h1>" +
"<p>Ésto <b>es</b> un <i>párrafo</i>.</p>");
editorPane.setBounds(10, 92, 481, 134);
contentPane.add(editorPane);
Con la función setContentType se establece el tipo de texto, que permite: text/plain para texto normal y corriente, con text/rtf podemos poner texto enriquecido siguiendo su especificación, y el text/html para páginas web.
Aquí tienen más información sobre los JEditorPane en la documentación oficial.

JTextPane

Éste es un subcomponente de JEditorPane, podemos usarlo exactamente igual pero además añade que podemos insertar dentro otros componentes con la función insertComponent(nombreComponente).
JTextPane textPane = new JTextPane();
textPane.setContentType("text/html");
textPane.setText("<h1>Título</h1>" +
"<p>Ésto <b>es</b> un <i>párrafo</i>.</p>");
JButton boton = new JButton("Ésto es un botón");
textPane.insertComponent(boton);
textPane.setBounds(10, 262, 481, 125);
contentPane.add(textPane);
Se pueden añadir todo tipo de componentes, o por lo menos la declaración de insertComponent recibe un parámetro de tipo Component, con lo que habría que probar a ver si los admite todos.

Terminando

Es interesante la función setPage(URL) que admite tanto el JTextPane como el JEditorPane, con la que podemos poner una página de Internet o de la red local dentro del componente. En el ejemplo adjunto abajo se utiliza la función setPage para cargar contenido HTML. Haciendo un navegador casero.

Es interesante que también admite editar el contenido el JTextPane y el JEditorPane, con lo que hay posibilidades para hacer un editor de páginas web, por ejemplo, o de texto enriquecido. Se le pueden añadir unos botones alrededor de la ventana para cambiar los formatos.. etcétera.. ya cada uno que imagine y que haga, hay mucho juego.

Bueno con ésto ya hay para hecharle un buen vistazo a éstos componentes, espero que sirva. A continuación les dejo todo el código de ejemplo. También adjunto un fichero comprimido con todo, hay un .jar ejecutable dentro para verlo en marcha. Para ejecutarlo sólo necesitas el JRE instalado. Aquí va el código:

import java.awt.EventQueue;
import java.io.IOException;
import java.text.ParseException;

import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.border.EmptyBorder;
import javax.swing.text.MaskFormatter;

public class Principal extends JFrame {

// éste es el panel principal que todo lo contiene
private JPanel contentPane;

// función que primero se ejecuta creando el JFrame
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Principal frame = new Principal();
// visualiza el frame
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}

// constructor de la clase,
// se usa para crear todos los componentes y programar
// todo el funcionamiento
public Principal() throws ParseException {

// se configura la ventana...
setTitle("Java Swing 7 Textos y otros by Jnj");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 517, 438);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);

// la primera etiqueta
JLabel lblJformattedtext = new JLabel("JFormattedTextField");
lblJformattedtext.setBounds(10, 11, 133, 14);
contentPane.add(lblJformattedtext);

// la etiqueta del JEditorPane
JLabel lblJeditorpane = new JLabel(
"JEditorPane que accede a http://localhost/");
lblJeditorpane.setBounds(10, 67, 250, 14);
contentPane.add(lblJeditorpane);

// la etiqueta del JTextPane
JLabel lblJtextpane = new JLabel("JTextPane");
lblJtextpane.setBounds(10, 237, 109, 14);
contentPane.add(lblJtextpane);

// la caja de texto formateado
// con una máscara de formato
JFormattedTextField formattedTextField = new JFormattedTextField(
new MaskFormatter("(####)#########"));
formattedTextField.setBounds(10, 36, 481, 20);
contentPane.add(formattedTextField);

// el JEditorPane que usa una página web
// accediendo al servidor web de nuestra
// máquina local
JEditorPane editorPane = new JEditorPane();
// es obligatorio usar el try catch para capturar errores
try {
// establece la página
editorPane.setPage("http://localhost/");
} catch (IOException e) {
e.printStackTrace();
}
editorPane.setBounds(10, 92, 481, 134);
contentPane.add(editorPane);

// y el JTextPane
JTextPane textPane = new JTextPane();
// se establece el tipo
textPane.setContentType("text/html");
// con un texto en HTML
textPane.setText("<h1>Título</h1>" +
"<p>Ésto <b>es</b> un <i>párrafo</i>.</p>");
// se crea un botón
JButton boton = new JButton("Ésto es un botón");
// se inserta el botón dentro de la caja de texto
textPane.insertComponent(boton);
textPane.setBounds(10, 262, 481, 125);
contentPane.add(textPane);
}
}

Un saludo.


Los Reyes Magos les habian traido virus a los de Oracle

2013-01-13 - Categorías: General
Parece ser que los Reyes Magos les han traido virus al final a los de Oracle, ¿tan malos han sido en 2012?

Antes de nada gracias por la información que me habeis enviado sobre el problema que corría últimamente por Internet sobre Java. Se estan llenando los titulares de la noticia, con contenidos tremendistas haciendo eco de las resoluciones de los expertos recomendando desinstalar incluso completamente Java de nuestras máquinas:
http://www.fayerwayer.com/2013/01/se-recomienda-desinstalar-java-ahora-mismo-tras-el-descubrimiento-de-grave-vulnerabilidad/
http://www.20minutos.es/noticia/1698519/0/recomiendan/desactivar-java/fallo-seguridad/
Java viene a ser el lenguaje más utilizado en programación de los últimos años, y como no, cualquier noticias de ésta índole llama mucho la atención. Java está en el punto de mira de muchos, su máquina virtual está instalada en muchos dispositivos, y sus programas se pueden ejecutar en todos lados.
Si te pones en la piel de un virus, lo mejor que querrías tener es tener tu código precompilado en bytecodes compatibles con la JRE para poder ejecutarte en toda máquina compatible con Java. Pues ésto es lo que ha pasado. Y viene pasando últimamente cada vez más. Pero me he molestado un poco en investigar y quitarle un poco de leña al fuego, averiguando en que consiste exactamente ésta vulnerabilidad.
http://www.genbeta.com/seguridad/una-vulnerabilidad-de-java-no-resuelta-compromete-la-seguridad-de-nuestros-equipos
http://www.torontosun.com/2013/01/12/java-security-fixing-coming-shortly-oracle-corp

Resulta que el problema está en el plugin que ejecuta Java en los navegadores. Es decir, los virus que se cuelan en tu ordenador lo hacen a través del plugin Java para el navegador. Bastaría con desactivar dicho plugin para evitar contagio. O simplemente no entrando en páginas web con contenido dudoso.

El problema está en la JRE 1.7 update 10, lo que estoy leyendo es que algunos escritores dicen que en todas las anteriores versiones también existía y otros que no, así que mejor no digo nada al respecto. Para desactivar Java en nuestro navegador, por lo menos hasta que solucionen el problema, a continuación dejo el link por si tienes la versión 10 de Java 7:
http://www.java.com/en/download/help/disable_browser.xml
Simplemente deshabilitándolo desde el panel de control de Java ya estamos más «seguros».
En fin, ésto es lo que tiene ser una de las tecnologías más usadas. Mientras que Java sea uno de los principales lenguajes de programación seguira siendo foco de ataques a sus fallos de seguridad. Igual ha venido siendo con Windows desde siempre, al ser el Sistema Operativo más usado y no por ello hemos dejado de usarlo. También le ha pasado a los de Apple con más que muchos ordenadores infectados, incluso sin ningun antivirus instalado porque nos pensamos falsamente: «Un Mac no tiene virus.». Y veremos a ver qué pasa con Android y otros Sistemas Operativos a medida que vengan siendo más utilizados. Serán siendo foco de los creadores de virus.

Pero bueno, yo que invierto tiempo con Java, ésta noticia me tocaba el alma.

Un saludo.


Mozilla Firefox: el zorro cada vez más rápido

2013-01-11 - Categorías: General
Cuanto más leo más me sorprende su historia y rumbo que llevan los desarrollos, tanto de la Fundación Mozilla, como en concreto, de su caballo de batalla, el Mozilla Firefox. Hoy he actualizado a la versión 18 del Firefox y me he puesto manos a la obra para éste post. Desde el Netscape, rivalizando con el Internet Explorer y con Chrome también, viene a ser un caso de estudio y una opción nada desechable.

En algunos desarrollos, tratando de seguir al 100% los estándares del Consorcio W3 que dirigen el cotarro, me he llegado a encontrar con problemas a la hora de visualizar o con el funcionamiento de la interfaz por problemas de compatibilidad entre navegadores. Según el que utilizaba cambiaba su funcionamiento. Donde se alineaba a la izquierda o derecha en una tabla con columnas agrupadas, ahora se alineaba al centro en otro navegador; aparte de los clásicos problemas con el vídeo y sonido al usar HTML4, resulta que los navegadores toman por defecto unos valores u otros. 
Total que acabo instalándome los principales navegadores para hacer las pruebas:
Safari
…en orden de uso. Cabe indicar que si usas Windows se complica encontrar la versión de Safari, pero al final buscando desde Google que todo lo encuentra me descargo la versión 5.1.7. Cuál será la razón por la que Apple no nos da el Safari con fácil acceso desde su web.
Leyendo un poco sobre Firefox resulta que viene a ser el único navegador de los principales, que no está desarrollado ni soportado por una empresa con ánimo de lucro. Ésto lo hace cada vez más interesante, sobre todo para mí que pienso que las soluciones gratuitas, con código fuente libre, son una de las opciones más interesantes, no sólo por su coste cero, sino también porque vienen siendo soluciones cada vez más probadas y con gran cantidad de usuarios. Será porque funcionan realmente bien.
Haciendo un repaso a lo que ha sido 2012 para Mozilla:
Se han añadido todo tipo de compatibilidades. Y después de haberse quedado un poco retrasado en cuestión de velocidad de funcionamiento, comparándolo con los demás navegadores… ahora viene cogiendo carrerilla y con la versión 18 destaca su velocidad, mejorada una vez más. Compatibilidad con tabletas. Funciones de programación avanzada con Javascript, como el BananaBread. La inclusión del IonMonkey para compilar Just-In-Time las aplicaciones Javascript y correr a toda velocidad…
En fin otra joya de la informática, que al ser desarrollado sin ánimo de lucro, no tenía otra opción que recomendarlo. Así que si no te has instalado el Firefox, ya estás tardando… xD
Si tiene tiempo, no se deje por probar el BananaBread.

Mapas conceptuales y construcción del conocimiento con Freeplane

2013-01-06 - Categorías: General
Ya han venido los Reyes Majos, y os han dejado virus para los que habeis sido malos. Y para los que habeis sido buenos os han dejado un buen programa que curiosear, el Freeplane. A fecha de hoy la versión que tengo es al 1.2.20 del Freeplane, lo he probado con el JRE 7 en un Windows 7.
Aún con mi edad sigo estudiando, sobre todo en la informática si no te actualizas frecuentemente te quedas obsoleto, desfasado, finito… He estado preparando unos exámenes en éstos días y he estado complicándome la vida un poco en buscar un programa que me sirva para organizar mis ideas. No soy vago a la hora de coger papel y lápiz para hacerme esquemas o resolver los problemas sobre el papel antes de pasarlos a limpio. Pero con todo lo que avanza las TI (Tecnologías de la Información), vienen siendo útil todos éstos programas que nos hacen la vida un poco más fácil.
Como buen fan del software GNU, del gratuito, o de los programas con licencias o versiones gratuitas. Les presento el Freeplane para el que no lo conozca. Nació del archiconocido FreeMind, que a fecha de hoy anda un poco desactualizado. Viene a ser la continuación del FreeMind, cuyos códigos fuentes iniciales son los propios del FreeMind, pero han ido añadiendo más y más funciones como exportar en formato PDF, en HTML, en imágenes tanto vectoriales (SVG) como normales (JPG, PNG…), etcétera. Nos permite cambiar los estilos de cada nodo, las formas de las llaves, las flechas, añadir iconos a los nodos, podemos poner textos grandes en un nodo, o incluso enlazar a páginas web o archivos externos desde nuestros esquemas.
Como dice en su Acerca de… es un programa libre para creación de mapas conceptuales y construcción del conocimiento. Su licencia es GNU, con lo que se puede usar para trabajar o de forma personal sin coste alguno. Rivaliza con el XMind que viene siendo también un referente en éste campo, también es multiplataforma, disponible para Windows, Linux y Mac, está hecho en Java y funciona de maravilla todo lo que he probado.
Tiene innumerables opciones. El ejemplo que nos enseña el programa nos puede mostrar en líneas generales para qué lo podemos usar:
Yo lo tengo en castellano, haciendo click en el menú Ayuda->Documentación te saldrá un esquema como el de la imagen de abajo donde se puede aprender a usar todo lo que se necesite llegado el momento. Hasta tiene una opción en Ayuda->Pedir una Característica nueva que me sorprende que exista. En fin, toda una joya de la informática.

Para instalártelo, leer más sobre él o lo que sea:

http://freeplane.sourceforge.net/

Un saludo!


Java Swing 6: Los componentes básicos

2013-01-01 - Categorías: Java / Java Swing
¡¡Feliz Año Nuevo!!
Hace ya un tiempo que no escribo, así que voy a tratar de que éste año sea mejor que el anterior y comienzo por avanzar en mis investigaciones con Java, así que os dejo éste post por si a alguien le sirve…
Sigo escudriñando los componentes de Swing, a ver cómo son los más simples, que no faltan en cualquier programa. Si lo que buscas es aprender rápido lo necesario para usarlos, éste es tu post xD He utilizado la versión 7 del JDK y Eclipse Juno.

Si vas a seguir éste tutorial desde cero, lo suyo sería que hicieras un nuevo proyecto, crearas un nuevo JFrame con el generador de código de Eclipse y fueras al Swing Designer. Es decir, entras al modo de diseño para editarlo intentando hacer algo como la imagen de arriba, usando las herramientas que ves aquí abajo:
Queda cada vez menos componentes de los presentados en el post ‘Java Swing 1’. Así que vamos al grano.

JLabel

Es una etiqueta. Con el diseñador ponemos el texto en el valor text, se puede cambiar en el código con la función nombreEtiqueta.setText(«Cadena»); aunque en el código fuente del ejemplo se ha puesto el texto en el constructor al usar JLabel lblEtiqueta = new JLabel(«Etiqueta»);

JTextField

Es una caja de texto. Se usa de igual manera que una etiqueta a la hora de programar o diseñar la interfaz, pero su diferencia con la etiqueta es que el usuario puede cambiar el contenido de la caja escribiendo en ella, con la etiqueta no puede hacerlo. Tendremos también la función nombre.setText(«Cadena»); anterior. Con variable = txtCajaDeTexto.getText(); podemos tener el contenido de la caja de texto en la variable. Éste componente sólo admite una línea.

JComboBox

Significa cuadro combinado, como se puede ver en el ejemplo, es una lista de elementos desplegable donde el usuario puede elegir entre las opciones que le demos. La elección la podemos tener con a función variable = comboBox.getSelectedIndex();

JButton

Es un simple botón, con el que al hacer click programamos lo que necesitemos. En el ejemplo se muestra un diálogo simple con:
btnBotn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(frame, "Ésto es un botón simple.");
}
});
Tambien se puede cambiar el texto con el método .setText(cadena);

JCheckBox

Las casillas de verificación, que en ejemplo hay varias. Las podemos usar de una en una, o en grupo, poniéndolas dentro de un grupo, de manera que cuando se selecciona una las demás se des-seleccionan automáticamente.
Para saber si un JCheckBox está ‘checkeado’ debemos usar la función nombreCheckBox.isSelected(); que devolverá true o false.

JRadioButton

Los botones de radio, JRadioButton para los amigos, se usan de igual manera que los JCheckBox. La diferencia es que tradicionalmente se usan para elegir una entre varias opciones, mientras que los JCheckBox normalmente se usan para elegir en varias opciones si se desean o no, sin que unas excluyan a las otras. Pero en realidad se pueden usar igual dependiendo de si los agrupamos o no. En el ejemplo se han agrupado los botones de radio con el código:
ButtonGroup radioGroup = new ButtonGroup();
radioGroup.add(rdbtn1);
radioGroup.add(rdbtn2);
Ésto de aquí arriba lo que hace es que si elegimos el rdbtn1 entonces el rdbtn2 se des-selecciona y viceversa. Así de simple ocurre si también agrupamos los JCheckBox, es decir, en los elementos de un grupo sólo estará seleccionado uno.

JToggleButton

Llamado botón de activación, se usa de nuevo igual que un JCheckBox o un JRadioButton, creo que sobran las explicaciones aquí porque tenemos las mismas funciones y comportamientos, sólo cambia su apariencia por la forma de un botón que se mantiene pulsado cuando está activado.

JTextArea

Es un área de texto de varias líneas, se usa igual que el JTextField pero con la diferencia de que admite varias líneas. Podemos establecer el número de líneas con nombre.setRows(n); y tenemos también las funciones nombre.getText() y nombre.setText(). En el ejemplo se establece el texto de la forma:
txtrAreaDeTexto.setText("Arearnderntexto.");
Podemos ver que con rn se produce un salto de línea. Ésto nos puede servir en muchos otros sitios para hacer un salto de línea, así que de memoria a aprendérselo.

JPasswordField

Es un área de contraseña, es decir, un área de texto pero con la diferencia de que los caracteres no se muestran para que el usuario del ordenador de al lado no pueda leer las contraseñas que pones en tu pantalla. La diferencia con un JTextField es que para conseguir la cadena de caracteres que ha puesto el usuario hay que usar la función nombre.getPassword();

JSpinner

Ésto es una caja donde con un par de botones cambiamos los valores. Traducido se llama ‘hilandero’, otra palabra nueva para mi vocabulario, nunca la habia oido ni leido. Por defecto se configura para que recorra los enteros, si le das a la flecha arriba suma uno al valor que haya 1, 2, 3, 4, 5… Si le das abajo resta de la forma 3, 2, 1, 0, -1, -2, -3…
Con spinner.getValue(); obtenemos el valor elegido. Va a devolver un objeto del tipo correspondiente, puede ser una fecha o una lista de elementos.
Para configurarlo hay que acceder en el modo Design a la propiedad model. Internamente utiliza la función setModel() para establecer una lista de elementos que utiliza el componente. Éstos vectores son habituales en varios componentes Swing y nos van a facilitar la vida. Por resumirlos, los ListModel son vectores, y dependiendo del tipo de componente los elementos del vector van a ser de un tipo o de otro. En el JList se ha establecido uno para verlo claro.

JList

Es una lista seleccionable. Estableciendo la propiedad model pondremos los elementos fácilmente con el Swing Designer. Si vamos al código veremos que se genera un ListModel especial para el tipo JList, el AbstractListModel, y entonces podremos acceder a los elementos seleccionados con las funciones siguientes:
entero = list.getSelectedIndex();
vectorDeEnteros = list.getSelectedIndices();
elemento = list.getSelectedValue();
vectorDeElementos = list.getSelectedValues();
La lista permite selección múltiple, por eso que tenemos las funciones que devuelven vectores.

JProgressBar

Es una barra de progreso. Con nombre.setValue(nuevoValor) y nombre.getValue() podemos cambiar o saber el valor que tiene en cada momento. Su manejo es sencillo y pienso que con esas dos funciones en bastante para empezar con ello.

JScrollBar

Es una barra de desplazamiento. Se usa igual que la barra de progreso a la hora de programar, pero añade que el usuario puede moverla, de manera que puede cambiar el valor de su posición. Con ésto que añade es interesante capturar el evento para hacer algo cuando el usuario cambia su posición, para ello con el boton derecho en el componente la damos al evento de cambio de ajuste:
En el código del ejemplo se puede ver que cuando se mueve la barra de desplazamiento se van a ajustar tanto la barra la progreso como el deslizador que viene a continuación.

JSlider

En castellano se llama deslizador. Funciona igual que la barra de desplazamiento, pero nos permite un mayor ajuste, pudiendo mostrar una regla con los números. Para que se vea la regla debemos poner los valores que se ven en la imagen siguiente:
Si no configuramos éstos valores en el editor de diseño no se verán los números. De igual manera que los anteriores, con getValue() tendremos el valor actual.
En la barra de desplazamiento se ha capturado el evento que se dispara al cambiar el ajuste. Para el deslizador el evento que se dispara cuando se mueve el deslizador se llama cambio de estado, como se ve en el código fuente:
slider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent arg0) {
progressBar.setValue(slider.getValue());
scrollBar.setValue(slider.getValue());
}
});

JSeparator

Simplemente es una línea de separación, una raya, que ya puse en el post anterior sobre los menús. Se puede poner también en el JFrame, concretamente en el panel, para dibujar una separación.

Terminando

Todo lo anterior se puede ver al detalle escudriñando un poco el código fuente generado con el Swing Designer y un poco programado manualmente:
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;

import javax.swing.AbstractListModel;
import javax.swing.ButtonGroup;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JProgressBar;
import javax.swing.JRadioButton;
import javax.swing.JScrollBar;
import javax.swing.JSeparator;
import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.SwingConstants;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

// ÉSTO ES LA CLASE PRINCIPAL QUE EXTIENDE DE JFRAME...
public class Principal extends JFrame {

private JPanel contentPane;
private JTextField txtCajaDeTexto;
static Principal frame;
private JPasswordField passwordField;

// la función que primero se ejecuta que crea
// el frame en memoria...
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
frame = new Principal();
// ... y lo visualiza
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}

// aquí está el constructor de la clase que todo
// lo programa...
public Principal() {
// se contruye la ventana
setTitle("JavaSwing 6 Componentes bu00E1sicos by Jnj");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 458, 363);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);

// la etiqueta
JLabel lblEtiqueta = new JLabel("Etiqueta");
lblEtiqueta.setBounds(10, 11, 67, 14);
contentPane.add(lblEtiqueta);

// la caja de texto
txtCajaDeTexto = new JTextField();
txtCajaDeTexto.setText("Caja de texto");
txtCajaDeTexto.setBounds(10, 36, 152, 20);
contentPane.add(txtCajaDeTexto);
txtCajaDeTexto.setColumns(10);

// el cuadro combinado
JComboBox comboBox = new JComboBox();
// los elementos
comboBox.setModel(new DefaultComboBoxModel(new String[] {"Elemento 1", "Elemento 2", "Elemento 3"}));
// comienza seleccionado el elemento 1
comboBox.setSelectedIndex(1);
comboBox.setBounds(10, 67, 191, 20);
contentPane.add(comboBox);

// el botón
JButton btnBotn = new JButton("Botu00F3n");
// cuando se pulsa hace ésto
btnBotn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(frame, "Ésto es un botón simple.");
}
});
btnBotn.setBounds(53, 95, 89, 23);
contentPane.add(btnBotn);

// la casilla de verificación
JCheckBox chckbx = new JCheckBox("Casilla de verificaciu00F3n");
chckbx.setSelected(true);
chckbx.setBounds(10, 125, 191, 23);
contentPane.add(chckbx);

// los botones de radio
JRadioButton rdbtn1 = new JRadioButton("RadioButton 1");
rdbtn1.setBounds(10, 151, 109, 23);
contentPane.add(rdbtn1);

JRadioButton rdbtn2 = new JRadioButton("RadioButton 2");
rdbtn2.setBounds(10, 177, 109, 23);
contentPane.add(rdbtn2);

// el grupo para los botones
ButtonGroup radioGroup = new ButtonGroup();
radioGroup.add(rdbtn1);
radioGroup.add(rdbtn2);

// otras casillas de verificación que se van a agrupar
// para ver el comportamiento
JCheckBox chckbx1 = new JCheckBox("CheckBox 1 agrupado");
chckbx1.setBounds(10, 203, 166, 23);
contentPane.add(chckbx1);

JCheckBox chckbx2 = new JCheckBox("CheckBox 2 agrupado");
chckbx2.setBounds(10, 229, 152, 23);
contentPane.add(chckbx2);

// el grupo para las casillas de verificación
ButtonGroup chkGroup = new ButtonGroup();
chkGroup.add(chckbx1);
chkGroup.add(chckbx2);

// el botón de activación
JToggleButton tglbtn = new JToggleButton("Botu00F3n de activaciu00F3n");
// que está seleccionado inicialmente
tglbtn.setSelected(true);
tglbtn.setBounds(10, 259, 166, 23);
contentPane.add(tglbtn);

// el área de texto
JTextArea txtrAreaDeTexto = new JTextArea();
// con una linea en el borde
txtrAreaDeTexto.setBorder(new LineBorder(new Color(0, 0, 0)));
// tres lineas de texto permitidas
txtrAreaDeTexto.setRows(3);
// el texto
txtrAreaDeTexto.setText("Arearnderntexto.");
txtrAreaDeTexto.setBounds(224, 11, 205, 58);
contentPane.add(txtrAreaDeTexto);

// el texto de contrasela
passwordField = new JPasswordField();
passwordField.setBounds(224, 80, 152, 20);
// contraseña inicial
passwordField.setText("supercontraseña");
contentPane.add(passwordField);

// el llamado 'hilandero'
JSpinner spinner = new JSpinner();
spinner.setBounds(224, 111, 101, 20);
contentPane.add(spinner);

// la lista
JList list = new JList();
// la declaración de los elementos
list.setModel(new AbstractListModel() {
String[] values = new String[] {"Elemento 1", "Elemento 2", "Elemento 3"};
// función que deveuelve el número de elementos
public int getSize() {
return values.length;
}
// función para acceder a cada elemento
// por ejemplo usando
//
// list.getModel().getElementAt(1)
//
// nos devolverá el elemento "Elemento 2"
public Object getElementAt(int index) {
return values[index];
}
});
list.setSelectedIndex(1);
list.setBounds(224, 142, 67, 52);
contentPane.add(list);

// el separador
JSeparator separator = new JSeparator();
separator.setOrientation(SwingConstants.VERTICAL);
separator.setBounds(211, 11, 2, 297);
contentPane.add(separator);

// inicializacion de la barra de progreso,
// la barra de desplazamiento y el deslizador.
// los he puesto aquí juntos porque los uso
// después y era necesario.
final JProgressBar progressBar = new JProgressBar();
final JScrollBar scrollBar = new JScrollBar();
final JSlider slider = new JSlider();

// configuraciones de la barra de progreso
progressBar.setValue(50);
progressBar.setBounds(224, 203, 205, 14);
contentPane.add(progressBar);

// la barra de desplazamiento
scrollBar.addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent arg0) {
// mueve a la vez la barra de progreso y el deslizador
progressBar.setValue(scrollBar.getValue());
slider.setValue(scrollBar.getValue());
}
});
// valor inicial
scrollBar.setValue(50);
scrollBar.setOrientation(JScrollBar.HORIZONTAL);
scrollBar.setBounds(224, 233, 205, 23);
contentPane.add(scrollBar);

// el deslizador, capturando evento
slider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent arg0) {
// mueve la barra de progreso y la de desplazamiento
// cada vez que se mueve el deslizador.
progressBar.setValue(slider.getValue());
scrollBar.setValue(slider.getValue());
}
});
// valores para que salga la regla numerada
slider.setMinorTickSpacing(1);
slider.setMajorTickSpacing(10);
slider.setToolTipText("");
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.setBounds(224, 267, 200, 52);
contentPane.add(slider);

} // termina el constructor de la ventana
} // termina la clase
Un fichero .zip para descargar con todo el código fuente y un ejecutable .jar para verlo en acción lo tienen aquí: descargar ejemplo.
Para ejecutarlo es necesario por lo menos tener el JRE, recomiendo la última versión a ser posible, la 7.
Como viene siendo habitual, para más información, me remito a la documentación oficial:
Espero que haya servido.
Un saludo. 

© 2024 JnjSite.com - MIT license

Sitio hecho con WordPress, diseño y programación del tema por Jnj.