WordPress

Joomla! Platform 3: Bases de datos

2013-06-25 - Categorías: PHP
Ya llegó el calor, terminaron los exámenes de junio y parece que ya llega el verano, aunque hace poco aún estaba lloviendo en la costa mediterránea de España. Yo sigo con lo mío y hoy les traigo un acceso a bases de datos usando SQLite, una base de datos de dominio público, embebida, no necesita instalación y simplemente con que PHP tenga activada la extensión para ello ya podemos usarla.
Como viene siendo costumbre de la serie que escribo, me voy a centrar en el uso en un servidor web, con lo que el ejemplo es una página web. Se puede también ejecutar en línea de comando pero yo no uso PHP de esa forma así que… vamos al grano.


Materiales

  1. El framework Joomla Platform. Yo he usado la versión 12.3, la oficial veo que es la 12.1 y está en desarrollo la 13.1. Aquí hay más información para los curiosos como yo.
  2. Un entorno de desarrollo. Aquí ya para gustos estan los colores, Eclipse va muy bien y es multiplataforma.
  3. Un servidor para ejecutarlo. XAMPP funciona muy bien y también es multiplataforma.

Empezando

Descomprimo el framework en el directorio si es que no lo tengo ya, entonces hay que crear un fichero .php como en el ejemplo siguiente y veremos rápidamente como funciona:
...
<?php

// se importa la Plataforma Joomla.
require_once 'libraries/import.php';

class laWeb extends JApplicationWeb {
protected function doExecute()
{
$this->setBody("<html><body>");
$this->appendBody("<h1>Plataforma Joomla! SQLite</h1>");

// vector de configuración de la base de datos
// para sqlite sólo hace falta ésto
$option = array();
$option['driver'] = 'sqlite'; // tipo de bd
//$option['host'] = 'direccionhost.com'; // host
//$option['user'] = 'usuario'; //
//$option['password'] = 'contraseña'; //
$option['database'] = 'bdpruebas.sqlite'; // nombre de la bd
//$option['prefix'] = 'pref_'; // prefijo
$dbo = JDatabaseDriver::getInstance($option);

// se puede abreviar usando:
//$dbo = JDatabaseDriver::getInstance(array('driver' => 'sqlite', 'database' => 'bdpruebas.sqlite'));


// crea una tabla para las pruebas, la borra si existe
$dbo->setQuery("DROP TABLE IF EXISTS aleatorios");
$dbo->execute();
$dbo->setQuery('CREATE TABLE IF NOT EXISTS aleatorios (id INTEGER PRIMARY KEY, numero INTEGER)');
$dbo->execute();
$this->appendBody("<p>Creada la base de datos...</p>");

// inserta unos datos en la BD
for ($i = 0; $i < 10; $i++) {
$dbo->setQuery('INSERT INTO aleatorios (id, numero) VALUES (' . $i . ', ' . rand(0,99) . ');');
$dbo->execute();
}
$this->appendBody("<p>Insertados datos...</p>");

// lee la tabla
$this->appendBody("Listando con loadRowList ");
$dbo->setQuery("SELECT * FROM aleatorios;");
$resultados = $dbo->loadRowList();
foreach ($resultados as $res){
$this->appendBody( "<p>" . $res[0] . ", " . $res[1] . "</p>");
}

// lee la tabla de otra forma
$this->appendBody("Listando con loadAssocList ");
$dbo->setQuery("SELECT * FROM aleatorios;");
$resultados = $dbo->loadAssocList();
foreach ($resultados as $res){
$this->appendBody( "<p>" . $res['id'] . ", " . $res['numero'] . "</p>");
}

// lee de nuevo la tabla de otra forma
$this->appendBody("Listando con loadObjectList ");
$dbo->setQuery("SELECT * FROM aleatorios;");
$resultados = $dbo->loadObjectList();
foreach ($resultados as $res){
$this->appendBody( "<p>" . $res->id . ", " . $res->numero . "</p>");
}

$this->appendBody("</body></html>");

}
}

JApplicationWeb::getInstance("laWeb")->execute();
...

El ejemplo en descarga está aquí.

El resultado de ejecutarlo desde el navegador debe ser algo tal que así:

Plataforma Joomla! SQLite

Creada la base de datos…
Insertados datos…
Listando con loadRowList
0, 55
1, 4
2, 1
3, 76
4, 95
5, 62
6, 63
7, 16
8, 52
9, 73
Listando con loadAssocList
0, 55
1, 4
2, 1
3, 76
4, 95
5, 62
6, 63
7, 16
8, 52
9, 73
Listando con loadObjectList
0, 55
1, 4
2, 1
3, 76
4, 95
5, 62
6, 63
7, 16
8, 52
9, 73

Explicaciones

Lo que hace el programa es crear el archivo bdpruebas.sqlite si no existe, es un comportamiento peculiar de SQLite. Si usásemos otra base de datos como PostgreSQL o MySQL podríamos usar las sentencias SQL propias de cada base de datos. El código usa las funciones para cargar tablas de datos loadRowList, loadAssocList y loadObjectList. Ésto nos devuelve un objeto que almacenará los datos de la base de datos en nuestro programa. Hay otras funciones para cuando la consulta devuelve sólo una fila o sólo un dato por ejemplo.
Hasta aquí todo bien, pero entonces ¿porqué usar el framework y no usar directamente PHP como siempre sin framework?
Ahora a partir de las últimas versiones se han añadido más bases de datos aparte de la original MySQL, tenemos PostgreSQL, SQLServer, y se preveen el acceso a muchas otras. Ahora bien, tenemos una capa extra que nos va a independizar totalmente de la base de datos, siempre que no usemos las tradicionales sentencias SQL, como en el ejemplo anterior, y construyamos nuestra aplicación usando ésta herramienta. Puede que en un futuro querramos cambiar de base de datos o hacer posible que dicho cambio sea dinámico según configuración del usuario.

Independizando de la base de datos

La historia está en crear la query usando el framework. Tenemos la clase JDatabaseDriver que es la que nos provee de la conexión a la base de datos. Ahora sí, contruimos la $query usando la clase JDatabaseQuery y entonces obtendremos esa compatibilidad de las consultas, inserciones, actualizaciones y borrados de nuestro programa con varios tipos de bases de datos. He simplificado el ejemplo anterior:
...
<?php

// se importa la Plataforma Joomla.
require_once 'libraries/import.php';

class laWeb extends JApplicationWeb {
protected function doExecute()
{
$this->setBody("<html><body>");
$this->appendBody("<h1>Plataforma Joomla! Independizando de la base de datos</h1>");

//
$dbo = JDatabaseDriver::getInstance(array('driver' => 'sqlite', 'database' => 'bdpruebas.sqlite'));

// borrando los datos de la tabla aleatorios
// para tenerla limpia
$query = $dbo->getQuery(true);
$query->delete('aleatorios');
$dbo->setQuery($query);
$dbo->execute();

$this->appendBody("<p>Borrados los datos...</p>");

// inserta unos datos en la BD
for ($i = 0; $i < 10; $i++) {
// crear una nueva consulta
$query = $dbo->getQuery(true);

// se construye
$query->insert('aleatorios')
->columns('id, numero')
->values($i . ', ' . rand(0,99));

// se establece
$dbo->setQuery($query);

// se ejecuta
$dbo->execute();
}
$this->appendBody("<p>Insertados datos...</p>");

// consultado datos
$query->select('*')->from('aleatorios');
$dbo->setQuery($query);
$resultados = $dbo->loadObjectList();
foreach ($resultados as $res){
$this->appendBody( '<p>' . $res->id . ', ' . $res->numero . '</p>');
}

$this->appendBody("</body></html>");

}
}

JApplicationWeb::getInstance("laWeb")->execute();
...

Éste segundo ejemplo está en descarga aquí.

Utilizando la base de datos creada con el primer ejemplo, si guardamos éste segundo en otro fichero .php y lo ejecutamos en el navegador funcionará de forma similar. Ahora, si tenemos la base de datos distinta de SQLite, simplemente con cambiar la línea:
$dbo = JDatabaseDriver::getInstance(array('driver' => 'sqlite', 'database' => 'bdpruebas.sqlite'));
Haciendo la conexión con la base de datos que tengamos, nos aseguramos que el resto de consultas, inserciones, actualizaciones o borrados van a funcionar.

Terminando

Otra vez más, me remito para más información a la documentación oficial:

http://docs.joomla.org/J3.1:Accessing_the_database_using_JDatabasehttp://api.joomla.org/Joomla-Platform/Database/JDatabaseQuery.html#insert

Éste post al final se ha hecho bien largo, ¡otro testamento! xDD Es que las bases de datos lo merecen ¿no cree?

Espero que sirva.
Saludos.


Joomla! Platform 2: La fábrica de objetos de Joomla

2013-06-08 - Categorías: PHP
Hoy les escribo un poco más sobre Joomla y su framework de desarrollo en PHP, la Joomla Platform. Esto es una joya, aunque no se usa mucho de manera independiente al CMS puede ser que pronto se haga. Por lo menos mi opinión es que es un buen framework; simple, rápido y eficaz, una buena alternativa.
Siguiendo con la carnicería, sacando toda la casquería, las tripas y demás de todo lo que es el CMS y el framework. Y nos encontramos con la fábrica de objetos, la clase JFactory.
La fábrica de objetos se usa constantemente en el CMS, en el desarrollo de extensiones, y si queremos desarrollar un sitio web a partir del framework podemos usarla y de esta manera tendremos todo el proyecto mejor estructurado.

Materiales

  1. El framework, Plataforma Joomla para los amigos.
  2. Un entorno de desarrollo o editor de texto: Eclipse, Notepad++, Gedit, Vi, Notepad o el que sea que use..
  3. Un servidor web con PHP: Va muy bien el XAMPP

El ejemplo

Con ésto pequeño ejemplo se puede ver una forma muy simple de usar el framework:

...
<?php

// se importa la Plataforma Joomla.
require_once 'libraries/import.php';

// en éste ejemplo tan simple la clase la pongo aquí pero
// se debería poner en otro fichero
class laWeb extends JApplicationWeb {
protected function doExecute()
{
$this->setBody("<html><body>");
$this->appendBody("<h1>Plataforma Joomla! probando la fábrica</h1>");

// declara una variable que es un objeto para trabajar con emails
$emiliator = JFactory::getMailer();
$this->appendBody("<p>Versión de MAILER de la plataforma: " . $emiliator->Version);

$this->appendBody("</body></html>");

}
}

// instancio un objeto de la aplicación web
$app = JApplicationWeb::getInstance("laWeb");

// guardo la aplicación en el core
JFactory::$application = $app;

// uso la aplicación web que guardé directamente desde el core
JFactory::getApplication()->execute();
...

Descargar archivo con el ejemplo.

JFactory es un objeto, que sirve para acceder al núcleo del framework, es decir, nos va a dar acceso a todo tipo de objetos que, al instanciarlos en nuestro programa, podremos usarlos y ahorrarnos el desarrollo de éstos.

Explicaciones

En el ejemplo he usado la función getMailer() para tener acceso al objeto de tipo JMail que tenemos en el framework. Es una interfaz con la que podremos construir en un email con destinatario, asunto, mensaje, etcétera… y configurando los parámetros del servidor de email podríamos enviar.
Hay muchos otros objetos, para hacernos una idea general, la fábrica de Joomla nos proporciona las siguientes funciones con las que acceder a éstos:
  • getACL: para manejo de autorizaciones.
  • getApplication: almacena la aplicación.
  • getCache: la caché.
  • getConfig: las configuraciones del sitio.
  • getDate: para manejo de fechas.
  • getDbo: manejo de bases de datos.
  • getDocument: manejo de documentos de varios tipos.
  • getEditor: el editor.
  • getFeedParser: te da un XML ya parseado.
  • getLanguage: el lenguaje.
  • getMailer: el mailer del ejemplo.
  • getSession: manejo de sesiones.
  • getStream: manejo de esos objetos tan útiles a veces, los streams.
  • getURI: para URIs.
  • getUser: el usuario.
  • getXML: para manajar ficheros XML.
Me remito a la documentación oficial, como siendo costumbre para más información sobre cada función: http://api.joomla.org/
Podemos ver la implementación completa de la JFactory en el archivo /libraries/joomla/factory.php
Me siento friki de nuevo, otros leen, juegan a videojuegos… cuando tienen tiempo. Yo me complico la vida tratando de averiguar cómo los desarrolladores de Joomla, han hecho el CMS y su framework, me saltan chispas y estoy hechando humo, pero lo he disfrutado.. ¿éso es de friki no? xD Espero haber dado algo de luz sobre la JFactory.
Para cualquier mensaje, aquí abajo lo pueden dejar.
Un saludo.

Joomla! Platform 1: Configuración y otros datos, JConfig y JPlatform

2013-06-05 - Categorías: PHP
Continuando con la serie de minitutoriales sobre la Plataforma Joomla, en éste post voy a empezar a despellejar y destripar poco a poco ésta joya de la informática. A fecha de hoy Joomla es el CMS más utilizado en todo el mundo y hay una comunidad muy grande que lo mantiene.
Si vamos a usar un framework PHP, nos vamos a asegurar de que la aplicación va a seguir una estructura, un orden a la hora de programar. Cada archivo, módulo, subprograma, función… va a ser claro de su padre y de su madre. Pero si usamos un framework, cualquiera que lo conozca podrá colaborar en el proyecto más pronto que tarde, porque será más legible, tendrá menos líneas de código probablemente que si lo hubieramos desarrollado desde cero. Todo ésto porque nos ahorraremos unas cuantas líneas de código.

Así que veamos pues cómo lo han hecho…

Materiales

Simplemente 3 cosas para seguir éste minitutorial:
  1. Un servidor web con PHP como XAMPP, disponible para varios Sistemas Operativos, o el Uniform Server portable y para Windows.
  2. Nuestro editor o entorno de desarrollo preferido. Como por ejemplo Eclipse, Notepad++, etc…
  3. El CMS si queremos probarlo lo tenemos en castellano en http:/www.joomlaspanish.org. Y la Joomla! Platform, yo he usado la versión 12.1, que lo tenemos en descarga en http://api.joomla.org/.
Empezando
Supongo que nos manejamos bien en PHP y con nuestro editor de código fuente, y tambien sabemos poner en marcha un servidor servidor local para nuestras pruebas. Además doy por entendido que conocemos el CMS de Joomla! lo sabemos instalar y más o menos llevamos un nivel adecuado de su manejo. Si no es así recomiendo no seguir y mirar antes éstas cosas.
Usaré para muchos de los ejemplos la clase JApplicationWeb para usar el framework, por si acaso comento que no es necesario, pero para ejecutar con un servidor web y ver en un navegador los resultados hace falta.
Antes de seguir descomprimimos el fichero de la Plataforma Joomla en el directorio donde vamos a hacer las pruebas y configuramos el servidor para acceder a él. Si queremos probar el CMS lo que ponemos en el directorio es el paquete Joomla para instalarlo., que también trae incluido una versión de la Plataforma.
JConfig y el fichero de configuraciones
En el CMS de Joomla! el fichero de configuracion de la web es /configuration.php. Cuando descomprimimos una instalación nueva, y visualizamos el nuevo Joomla! lo que vamos a ver el módulo o subprograma contenido en el directorio de instalación /installation. Dicho directorio está destinado a configurar la nueva instalación de Joomla! con una serie de formularios que nos guian paso a paso para poner todas las configuraciones, además de crear las tablas en la base de datos e introducir los datos necesarios para comenzar a usarlo.
Después de la instalación se debe de borrar el directorio /installation y se habrá creado dicho fichero /configuration.php. Simplemente tiene la clase JConfig que es un conjunto de variables. En el framework nos viene un ejemplo en /libraries/config.example.php como el siguiente:
<?php
class JConfigExample
{
public $dbtype = 'mysql';
public $host = 'localhost';
public $user = '';
public $password = '';
public $db = '';
public $dbprefix = 'jos_';
public $ftp_host = '127.0.0.1';
public $ftp_port = '21';
public $ftp_user = '';
public $ftp_pass = '';
public $ftp_root = '';
public $ftp_enable = 0;
public $tmp_path = '/tmp';
public $log_path = '/var/logs';
public $mailer = 'mail';
public $mailfrom = 'admin@localhost.home';
public $fromname = '';
public $sendmail = '/usr/sbin/sendmail';
public $smtpauth = '0';
public $smtpsecure = 'none';
public $smtpport = '25';
public $smtpuser = '';
public $smtppass = '';
public $smtphost = 'localhost';
public $debug = 0;
public $caching = '0';
public $cachetime = '900';
public $language = 'en-GB';
public $secret = null;
public $editor = 'none';
public $offset = 0;
public $lifetime = 15;
}
El ejemplo nos indica una forma de tener ordenadas las principales variables… En el siguiente ejemplo, he requerido el archivo de configuración de ejemplo que nos proporciona el framework para verlo como usaríamos uno nuestro:
<?php

// punto de entrada seguro
define('_JEXEC', 1);

require "libraries/import.php";
require "libraries/config.example.php";

class laWeb extends JApplicationWeb {
protected function doExecute()
{
$this->setBody("<html><body>");

$this->appendBody("<h1>Configuración de ejemplo</h1>");

// crea el objeto con las configuraciones
$conf = new JConfigExample();

// lista dicho objeto
foreach($conf as $nombre=>$valor)
$this->appendBody("<p><b>" . $nombre . "</b>: " . $valor . "</p>");

$this->appendBody("</body></html>");


}
}

JApplicationWeb::getInstance("laWeb")->execute();
En el punto de entrada seguro a Joomla, lo que se suele hacer es definir una variable, que en partes del CMS se busca y si no está declarada entonces termina la ejecución. Ésto se hace para evitar accesos directos por URL a ciertos archivos. Ésto es otro tema pero es de uso aconsejable.
La historia está en crear el objeto $conf declarado como un objeto de tipo JConfigExample, entonces en cualquier parte de nuestro programa podemos consultar los datos de configuración guardados en dicha variable $conf. En la práctica el CMS usa un objeto de tipo JConfig y se almacena para su uso posterior.
JPlatform, datos de la plataforma
Ésto es una clase destinada a guardar la información sobre la plataforma, versión del framework, nombre en clave y otros datos. Poniendo JPlatform::VARIABLE, podemos acceder a esos datos como en el ejemplo siguiente:
<?php
 
define('_JEXEC', 1);
require "libraries/import.php";

class laWeb extends JApplicationWeb {
protected function doExecute()
{
$this->setBody("<html><body>");
$this->appendBody("<h1>Información sobre la Plataforma Joomla!</h1>" .
"<p>Compilación: " . JPlatform:: BUILD . "</p>" .
"<p>Nombre en código: " . JPlatform:: CODE_NAME . "</p>" .
"<p>Copyright: " . JPlatform:: COPYRIGHT . "</p>" .
"<p>Texto del link: " . JPlatform:: LINK_TEXT . "</p>" .
"<p>Mantenimiento: " . JPlatform:: MAINTENANCE . "</p>" .
"<p>Producto: " . JPlatform:: PRODUCT . "</p>" .
"<p>Liberación: " . JPlatform:: RELEASE . "</p>" .
"<p>Fecha de liberación: " . JPlatform:: RELEASE_DATE . "</p>" .
"<p>Tiempo de liberación: " . JPlatform:: RELEASE_TIME . "</p>" .
"<p>Zona de tiempo de liberación: " . JPlatform:: RELEASE_TIME_ZONE . "</p>" .
"<p>Estado: " . JPlatform:: STATUS . "</p>" );

$this->appendBody("<p>Versión larga: " . JPlatform::getLongVersion() . "</p>" );
$this->appendBody("</body></html>");


}
}

JApplicationWeb::getInstance("laWeb")->execute();
Además de lo de aquí arriba también tenemos la función getShortVersion y isCompatible que devuelven una versión corta de la versión del framework que estemos usando y para comprobar si es compatible. isCompatible se usa para el CMS, para saber si es compatible el framework y el CMS.
Terminando
Los dos ejemplos anteriores los tienen en descarga aquí.

Con ésto me despido por hoy.

Saludos.


Java Swing 10: JTable segunda parte, un poco más sobre tablas

2013-05-07 - Categorías: Java / Java Swing

Siguiendo los minitutoriales de la serie Swing, he desarrollado éste post sobre tablas para aprender a usar un poco más las tablas. Vamos al grano.

Introducción

Es necesario:

  • Entorno de Desarrollo.
  • El JDK o JRE, yo he usado el JDK 1.7, pero ya Swing no sigue en desarrollo así que no tiene mucha importancia la versión que uses.

Trato de explicar cómo poner cajas seleccionables (checkbox), listas desplegables (combobox) y cajas de texto formateado, en una tabla. En el ejemplo he puesto una caja que sólo admite un número de 3 dígitos. Más adelante lo vemos.

Para manejar los datos puedes usar directamente el modelo de datos que autogenera un JTable, puedes usar un AbstractTableModel como aparece en muchos de los tutoriales que he encontrado por Internet, o puedes usar una implementación de DefaultTableModel, que internamente usa un vector con el que te permite añadir o borrar filas de forma dinámica. Yo he usado un DefaultTableModel que me ha parecido más interesante porque muchas veces necesitamos añadir o borrar datos de una tabla.

El código fuente

Descargar

package swing;

import java.awt.EventQueue;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.text.MaskFormatter;

public class JavaSwing10JTable2 extends JFrame {

private static final long serialVersionUID = 1L;
private JTable tabla;
private static MiModelo modelo;

// el main...
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
JavaSwing10JTable2 frame = new JavaSwing10JTable2();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}

// constructor de la ventana, aquí hace todo
public JavaSwing10JTable2() {

setTitle("Java Swing 9 El JTable 2");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 846, 331);

getContentPane().setLayout(null);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(10, 11, 810, 271);

getContentPane().add(scrollPane);

// usa mi modelo de datos
modelo = new MiModelo();
// crea la tabla con mi modelo
tabla = new JTable(modelo);

//
scrollPane.setViewportView(tabla);

// EDITORES PERSONALIZADOS EN LA TABLA
// la caja seleccionable, el checkbox lo pone sólo
// con la función getColumnClass
TableCellEditor editor;

// configura el combo
JComboBox comboBox = new JComboBox();
comboBox.addItem("Opción A");
comboBox.addItem("Opción B");
comboBox.addItem("Opción C");

// configura el campo de texto
JFormattedTextField campoTexto = null;
try {
// sólo admite 3 números
campoTexto = new JFormattedTextField(new MaskFormatter("###"));
} catch (Exception e) {
System.out.println(e.getMessage());
}

// combo a la columna 3
editor = new DefaultCellEditor(comboBox);
tabla.getColumnModel().getColumn(3).setCellEditor(editor);

editor = new DefaultCellEditor(campoTexto);
tabla.getColumnModel().getColumn(4).setCellEditor(editor);

// capturador de eventos del ratón en la tabla
// autogenerado con Eclipse
tabla.addMouseListener(new MouseListener() {

@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub

}

@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub

}

@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub

}

@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub

}

@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub

int fila = tabla.rowAtPoint(e.getPoint());
int columna = tabla.columnAtPoint(e.getPoint());

JOptionPane.showMessageDialog(null, "Valor de la celda: "
+ tabla.getValueAt(fila, columna).toString());
}
});

}

// modelo de datos, usa DefaultTableModel que internamente
// tiene un vector que nos permite por ejemplo añadir una fila
// fácilmente con addRow...
private static class MiModelo extends DefaultTableModel {

private static final long serialVersionUID = 1L;

private static final String[] nombresColumna = { "ID", "Un decimal",
"Caja seleccionable", "Lista desplegable",
"Campo texto formateado" };

Class[] tiposColumna = { Integer.class, Double.class, Boolean.class,
JComboBox.class, JFormattedTextField.class };

// constructor de la clase, simplemente pone unos datos en el vector de
// datos.
public MiModelo() {
super(nombresColumna, 0);

// carga unos datos iniciales...
for (int i = 0; i < 10; i++) {

Object[] aux = { i, Math.random(), i % 2 == 0, "Opción A",
"123" };

addRow(aux);

}
}

@Override
public Class getColumnClass(int columnIndex) {
// necesario para que dibuje la tabla con los tipos de columna
return tiposColumna[columnIndex];
}

}

}

También he añadido la captura de eventos del ratón. Al escribir tabla.addMouseListener(new Mouse… podemos usar la combinación de teclas Ctrl + espacio y Eclipse nos intentará autogenerar el código. Ésto mismo se puede usar en cualquier momento, si Eclipse detecta que estás escribiendo algo que conoce te lo pone en un listado o si sabe seguro lo que vas a escribir lo autogenera. Es un comportamiento muy útil.

Explicaciones

He usado un DefaultTableModel que internamente tiene un vector de filas, para poder usar la función addRow() y así simplificar todo un poco que para eso está la clase DefaultTableModel.

La historia de configurar la tabla está en la clase MiModelo, espero haber dejado lo bastante comentado el código como para no explicar de nuevo aquí lo que hace. De todas formas si queda duda, mensaje aquí abajo que lo contesto en cuanto pueda.

Podemos obtener el vector de datos de la forma:

Vector data = modelo.getDataVector();

Hay muchas funciones interesantes que nos permitirán hacer lo que necesitemos. Para hacerse una idea, en mi Eclipse pongo modelo. y se me despliega el listado de funciones que tengo disponibles:

Tenemos la que ya he dicho addRow para añadir una fila, getRowCount que devuelve el número de filas, y muchas más. Algunas funciones necesitan un post entero para explicarlas así que lo dejaré aquí.

Donde pone tabla.addMouseListener(… está todo lo relacionado con el ratón. Podemos programar acciones para cuando se hace click, cuando se aprieta el botón, cuando se libera, etcétera…

Sobre los editores personalizados en una tabla hay que decir que admite cajas chequeables, listas desplegables y campos de texto. Además se pueden crear nuevos editores, como por ejemplo el que cita en la documentación oficial de un editor de celda que nos permite elegir entre una tabla de colores.

Más información

Me remito como siempre a la documentación oficial:

http://docs.oracle.com/javase/tutorial/uiswing/components/table.html

De todas formas hay muy buena información en otras páginas web, espero que si has leido éste tutorial por lo menos te haya aclarado algo, o te sirva el código fuente.

No dudes en dejar un mensaje.

Saludos.


¡Adelante gadgeto PDF!

2013-05-03 - Categorías: General

Curioseando un programa que utilizo últimamente, el PDF24 Creator, además de en Windows he visto que tenía un Gadget para añadir en Blogger, es decir aquí. Así que lo he puesto en el menú para poder descargar una versión en PDF de lo que sea que esteis viendo en el blog. Lo teneis en la sección PDF para generar un fichero si es que te quieres guardar algo de lo que publico aquí.

Es un programa de Windows, 100% gratuito según reza en su página web donde lo teneis en descarga:

http://es.pdf24.org/

Funciona muy bien, te escanea documentos y los guarda a PDF de manera muy simple, puedes crear documentos de varias páginas, también instala una impresora virtual con la que puedes imprimir desde cualquier programa y te genera un documento. En fin, lo que he probado funciona muy bien y me ha sido muy útil. Todo un complemento digno de mención, y 100% gratis.

Lo único que le hecho en falta, aunque no lo he necesitado mucho la verdad, es un editor PDF con el que se puedan editar el contenido de un documento. Eso sí, a fecha de hoy lo que se puede hacer es mover las páginas de orden, de un documento a otro, pero no se puede editar una página en sí.

Buena herramienta de todas formas, seas programador o no. ¿He comentado que es 100% gratis?

Saludos.


Java Swing 9: La madre del cordero, el JTable

2013-05-02 - Categorías: Java / Java Swing

Siguiendo con los minitutoriales de Swing, ha llegado la madre del cordero del manejo de datos. Tarde o temprano necesitamos visualizar, modificar, borrar o guardar datos. Podemos hacer formularios, recorrer tablas guardadas en variables ocultas, usar listas, al final la manera más simple de mostrar muchos de éstos datos es una tabla, que en Swing se llama JTable.

Para seguir éste tutorial hace falta, un entorno de desarrollo (por ejemplo Eclipse), el JDK o el JRE, y un poco de paciencia xD

Si eres un máquina entonces descárgate directamente el código y no te olvides de visitarme de vez en cuando, a ver si aumentan las visitas =)

A saber

Antes de empezar hay que saber que un JTable es un componente Swing, que va a visualizar unos datos que se almacenan internamente en una variable de tipo TableModel. No se recomienda usar directamente pero si no lo necesitamos para qué vamos a complicarnos más la vida en usar otros métodos. Lo he usado para no complicar el ejemplo.

En el ejemplo se va a usar un DefaultTableModel el cual va a guardar referencia del TableModel que tiene la tabla. Entonces cuando se modifica, en éste caso añadiendo más filas, automáticamente la tabla se redibuja y muestra los datos actualizados. Se recomienda usar un AbstractTableModel para manejar los datos pero eso es otro tema.

Comenzando

Gran parte del código se puede generar con Eclipse. Así que los pasos a seguir para emepezar son:

  1. Crear un nuevo proyecto Java.
  2. Añadir un JFrame que genere todo el esqueleto de la ventana.
  3. En el Swing Designer en vista de diseño poner un Absolute Layer que nos permitirá posicionar los elementos donde queramos.
  4. Poner un JScrollPane y dentro de él el JTable, de esta manera si la tabla crece más que lo que vemos apareceran barras de scroll como las de la imagen anterior.
  5. El botón de abajo que meterá contenido en la tabla.

Hecho ésto hago doble click en el botón y me muestra todo el código recién generado listo para seguir implementando.

El código

A continuación el código lo más legible que he podido poner:

package swing;

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

public class JavaSwing9JTable extends JFrame {

// versión
private static final long serialVersionUID = 1L;

// la tabla
private JTable table;

// el modelo de tabla, aquí van a estar los datos.
private DefaultTableModel model;

// función principal
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
JavaSwing9JTable frame = new JavaSwing9JTable();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}

// constructor del frame que contruye toda la ventana...
public JavaSwing9JTable() {
//título
setTitle("Java Swing 9 El JTable");
// cuando cerramos la ventana se cierra la aplicación por completo
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// dimensiones y posición
setBounds(100, 100, 596, 331);
// establece una capa absoluta para posicionar los elementos donde queramos
getContentPane().setLayout(null);

// el panel con barras de scroll automáticas
JScrollPane scrollPane = new JScrollPane();
// dimensiones y posición del panel de scroll
scrollPane.setBounds(10, 11, 560, 227);

// se añade el panel de scroll a la ventana
getContentPane().add(scrollPane);

// nombre de las columnas
String[] columnNames = { "ID", "Un dato", "Otro dato" };

// creo un modelo de datos, sin datos por eso 'null' y establezco los
// nombres de columna
model = new DefaultTableModel(null, columnNames);
// creo la tabla con el modelo de datos creado
table = new JTable(model);

// se pone la tabla en el scroll
scrollPane.setViewportView(table);

// código del botón
JButton btnAadirLnea = new JButton("Meter contenido");
btnAadirLnea.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {

// aquí se añaden datos a la tabla
for (int i = 0; i < 100; i++) {

// creo un vector con una fila
Object[] aux = { i, i * 34, Math.random() };

// añado la fila al modelo
model.addRow(aux);

}

}
});
// dimensiones y posición del botón
btnAadirLnea.setBounds(10, 249, 267, 23);
// pongo el botón en la ventana
getContentPane().add(btnAadirLnea);

}
}

Descarga del código aquí.

Aclaraciones

Ésta es la forma más simple que he encontrado de usar una tabla de Swing. El paso siguiente es usar un AbstractTableModel, crearnos una clase que la implemente, con la que podemos entonces hacer cosas como meter cajas seleccionables o cuadros desplegables en las filas.

Más información

Hay mucha información en Internet, me remito primero a la documentación oficial, está en inglés y es muy extensa:

http://docs.oracle.com/javase/6/docs/api/javax/swing/JTable.htmlhttp://docs.oracle.com/javase/tutorial/uiswing/components/table.html

Espero que sirva. En próximos posts espero ver cómo controlar los clicks del ratón, esos temas que citaba de la clase AbstractTableModel, formularios maestro-detalle, etcétera…

Saludos!


¿Qué es un Bean de Java?

2013-03-27 - Categorías: Java

Podemos ver por todos lados la palabra Bean, significa vaina en inglés. Se puede leer en los lugares más variopintos: desde el NetBeans, los Java Beans, los Beans en Visual Studio, Eclipse, los Enterprise Java Beans, los Beans que usamos para acceder y guardar datos de nuestros programas.. pero ¿qué es un Bean de Java?

Continuar leyendo..

SQLite con Java

2013-03-07 - Categorías: General

Hoy les dejo un acceso a una base de datos SQLite, que últimamente está tan de moda. SQLite se usa en todo tipo de programas, es de dominio público, se puede incluir en tu programa añadiendo alguna librería muy ligera, y te da casi todas las funcionalidades que te puede dar cualquier otra BD relacional (de las que usan SQL).

Materiales

  1. Una vez más, mi entorno de desarrollo favorito, el Eclipse que supongo ya instalado. También se puede seguir el post usando otro entorno http://www.eclipse.org/
  2. Una librería hecha por completo en Java para usar SQLite, un tal Taro L. Saito, de Xerial nos deja en su repositorio para descargar en https://bitbucket.org/xerial/sqlite-jdbc/downloads
  3. El JDK instalado http://www.oracle.com/technetwork/java/javase/downloads/index.html 

 Un poco de teoría

Lo que he averiguado en mis investigaciones, más que nada con lo que me han explicado amigos, es que SQLite lo que no tiene son claves ajenas, con lo que la integridad referencial no está implementada dentro de su llamemosle «motor de la BD» es que tenemos integridad referencial, claves ajenas. Se pueden usar disparadores (triggers), cuando se hagan inserciones, modificaciones o borrados. Podemos usar BLOBs, definir los tipos de datos de las tablas, y un largo etcétera…

Según pone en la Wikipedia http://es.wikipedia.org/wiki/SQLite, la versión 3 de SQLite admite archivos de 2 Terabytes con incluso tipos de datos BLOB, con lo que podemos almacenar ficheros dentro de la base de dato. Con ésto creo que tenemos bastante, por lo menos para empezar a trastear las BD sin tener que instalar todo un señor motor de BD como los de Oracle o MS SQL Server, o los que más me gustan a mi como PostgreSQL o Firebird. En Java funcionan todas éstas BD de manera parecida, la idea principal es usar el JDBC que proporciona un estándar de conexión para conexión a bases de datos desde Java.

Manos a la obra

Al grano, después de un poco de teoría, antes de empezar con el código, hay que preparar el proyecto en Eclipse:

  1. Creo un nuevo proyecto de Java.
  2. Copio la librería de SQLite, en el proyecto, Eclipse te deja coger y arrastrar el fichero al Explodor de Proyectos con lo que te proguntará si quieres copiar o hacer un enlace externo al fichero. Prefiero copiarlo dentro del proyecto porqué así siempre estará incluido si es que creamos un ejecutable o nos llevamos el proyecto a otro ordenador.
  3. No basta con copiar la librería, tenemos que agregarla al Build Path del proyecto. Con el botón derecho del ratón en el explorador de proyectos, le damos a Build Path > Configure Build Path… Le damos a Add JAR… y elegimos el fichero que ya está dentro del proyecto. Debes ver una ventana parecida a ésta:

Hecho ésto ya podemos usar la librería desde cualquier clase que creemos dentro de éste proyecto. Entonces ya sí que sí, que empezamos creando una nueva clase, con un main. Yo he usado el generador de código de Eclipse y me ahorro tiempo. Entonces el código de ejemplo con el que se crea un fichero bdpruebas.db, luego dentro crea una tabla llamada tablapruebas, y va insertando valores aleatorios del 1 al 100 con un índice. Queda así:

package SqlitePack;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class ProbandoSqlite {

public static void main(String[] args) throws ClassNotFoundException {

Class.forName("org.sqlite.JDBC");

try {

// ESTABLECER LA CONEXIÓN
Connection conexion;
conexion = DriverManager.getConnection("jdbc:sqlite:bdpruebas.db");

// CREAR ENUNCIADO
Statement enunciado;
enunciado = conexion.createStatement();

// CREAR UNA TABLA NUEVA, LA BORRA SI EXISTE
enunciado.execute("DROP TABLE IF EXISTS tablapruebas;");
enunciado.execute("CREATE TABLE tablapruebas (id int primary key, aleatorio int);");

// INSERTAR DATOS
for (int i = 1; i <= 100; i++) {
enunciado.execute("INSERT INTO tablapruebas (id, aleatorio) values ("
+ i
+ ", "
+ Math.floor(Math.random() * 100 + 1) + ");");
}

// CONSULTA DATOS
ResultSet resultados;
resultados = enunciado.executeQuery("SELECT * FROM tablapruebas;");

// PROCESAR EL RESULTADO
while (resultados.next()) {
System.out.println("id " + resultados.getString(1)
+ ": aleatorio " + resultados.getString(2));
}

// CERRAR
resultados.close();
enunciado.close();
conexion.close();

} catch (Exception e) {
System.out.println("ERROR: " + e.getMessage());
}

}

}

Lo que hace el código es crear tres objetos: conexión, enunciado y resultados. Con conexión como su nombre indica, nos conectamos a la base de datos, si el fichero no existe lo crea, ésto es un comportamiento propio de SQLite. Con el enunciado lo que venimos a tener es una especie de «mesa de trabajo» con lo que vamos a atacar la base de datos con todo tipo de consultas o sentencias SQL. Es interesante el PreparedStatement para mejorar el funcionamiento interno de nuestro programa pero eso es otro tema. Luego con el objeto resultados en éste ejemplo lo que se hace es almacenar los resultados de la consulta.

Las sentencias SQL que se han usado lo que hacen es borrar la tabla si existe, la crean y llenan la tabla con los INSERT INTO. La última consulta con el SELECT lo que hace simplemente es listar todos los resultados de la tabla.

Dejo el proyecto en descarga como viene siendo costumbre xD

Descargar

Terminando

Para terminar, si pulsamos F11 en la ventana de consola debemos ver en los resultados algo tal que así:

id 1: aleatorio 4
id 2: aleatorio 70
id 3: aleatorio 94
id 4: aleatorio 40
id 5: aleatorio 86
id 6: aleatorio 40
id 7: aleatorio 89
id 8: aleatorio 80
id 9: aleatorio 79
id 10: aleatorio 14
id 11: aleatorio 69
id 12: aleatorio 2
id 13: aleatorio 12
id 14: aleatorio 62
id 15: aleatorio 74
id 16: aleatorio 53
id 17: aleatorio 45
id 18: aleatorio 44
id 19: aleatorio 56
id 20: aleatorio 40
id 21: aleatorio 81
id 22: aleatorio 75
id 23: aleatorio 97
id 24: aleatorio 78
id 25: aleatorio 63
id 26: aleatorio 30
id 27: aleatorio 13
id 28: aleatorio 21
id 29: aleatorio 68
id 30: aleatorio 58
id 31: aleatorio 25
id 32: aleatorio 92
id 33: aleatorio 88
id 34: aleatorio 77
id 35: aleatorio 38
id 36: aleatorio 45
id 37: aleatorio 18
id 38: aleatorio 47
id 39: aleatorio 60
id 40: aleatorio 51
id 41: aleatorio 90
id 42: aleatorio 90
id 43: aleatorio 96
id 44: aleatorio 34
id 45: aleatorio 47
id 46: aleatorio 89
id 47: aleatorio 97
id 48: aleatorio 58
id 49: aleatorio 78
id 50: aleatorio 49
id 51: aleatorio 23
id 52: aleatorio 82
id 53: aleatorio 12
id 54: aleatorio 92
id 55: aleatorio 51
id 56: aleatorio 99
id 57: aleatorio 56
id 58: aleatorio 9
id 59: aleatorio 14
id 60: aleatorio 1
id 61: aleatorio 4
id 62: aleatorio 80
id 63: aleatorio 80
id 64: aleatorio 97
id 65: aleatorio 89
id 66: aleatorio 47
id 67: aleatorio 3
id 68: aleatorio 73
id 69: aleatorio 34
id 70: aleatorio 99
id 71: aleatorio 22
id 72: aleatorio 38
id 73: aleatorio 69
id 74: aleatorio 22
id 75: aleatorio 6
id 76: aleatorio 97
id 77: aleatorio 28
id 78: aleatorio 47
id 79: aleatorio 21
id 80: aleatorio 50
id 81: aleatorio 89
id 82: aleatorio 22
id 83: aleatorio 71
id 84: aleatorio 98
id 85: aleatorio 45
id 86: aleatorio 20
id 87: aleatorio 12
id 88: aleatorio 29
id 89: aleatorio 75
id 90: aleatorio 11
id 91: aleatorio 54
id 92: aleatorio 24
id 93: aleatorio 86
id 94: aleatorio 89
id 95: aleatorio 90
id 96: aleatorio 39
id 97: aleatorio 34
id 98: aleatorio 1
id 99: aleatorio 37
id 100: aleatorio 66

Ya les dejo con ésto, espero que a alguien le sirva, un saludo.


Java hasta la médula de Linux

2013-02-23 - Categorías: General
Un día más, curioseando con mi Eclipse, probando a ver si ponía en marcha EGit para usar repositorios Git llego a encontrar un curioso proyecto que está llevando a cabo Pekka Enberg. Pekka es un ingeniero finlandés que dirige el Jato: a JIT-only virtual machine for Java. Que viene a ser un compilador de Java pero que va incluido como un módulo del Kernel de Linux.

Viene a ser una implementación «open source» de la máquina virtual de Java, dando soporte a la especificación Java SE Edición 7.

Antes de la versión 7 de Java, Linux no debía incluír la máquina virtual de Java en sus distribuciones. En la versión 7, lo que se ha hecho con Java principalmente es extraer de la máquina virtual las librerias propietarias, dejando sólo las librerías de las que se tiene el código fuente, que no son propietarias y son gratuitas, con lo que ya se puede usar la JVM como si de un programa GNU fuera, resumiendo a groso modo. Éste era un sueño que tenía Sun antes de su desaparición por ser absorbida por la macroempresa Oracle. Al final muchos propietarios de las librerías han liberado sus códigos y otros, reticentes, han sido excluidos de la versión 7 y reemplazados por otros. Ya hace tiempo de la primera versión de la JVM 7 pero es importante para ponerse en situación.
Java, como principal, o como uno de los principales lenguajes de programación, se está asentando fuertemente en el mundo Linux. Líder en la implantación de nuevos servidores, Linux está siendo una alternativa más que buena en los nuevos sistemas, y Java está afianzándose hasta la médula con éste «nuevo» módulo del kernel. A fecha en que escribo ya van tres años desde los primeros pasos del módulo, va por la versión 0.3. Les dejo unos enlaces para los más curiosos:

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.

© 2024 JnjSite.com - MIT license

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