La sociedad niega nuestra manera de pensar

1/ Esos somos nosotros, lo Diferente. Ratas de la tecnología, nadando en el océano de la información. 2/ Estamos cohibidos, pequeños chicos de colegio, sentados en el último pupitreSigue leyendo “La sociedad niega nuestra manera de pensar”

Usando GtkTreeView generado en Glade con Java

La presentación de datos en vista tabular es omnipresente en la mayoría de las aplicaciones, la implementación de TreeView representa los datos de un TreeModel en forma tabular, ya que se utiliza tanto para generar datos en forma de lista como para permitir al usuario seleccionar uno o más elementos de una lista. TreeView widget es la parte de la vista del diseño modelo/vista/controlador GTK, con una de las subclases TreeModel que suministra el modelo de datos.

Para construir un TreeView es necesario saber que se compone de una o más columnas verticales llamadas TreeViewColumn‘s, los CellRenderer‘s empacan los datos. Un CellRenderer hace el trabajo de tomar datos del TreeModel subyacente y presentarlos en TreeViewColumn. Hay una familia de CellRenderers para diferentes tipos de datos subyacentes, pero usarás CellRendererText casi exclusivamente.

Un TreeModel viene en dos formas para el almacenamiento de datos: ListStore para una lista de filas y TreeStore para datos que tienen una relación jerárquica entre las filas.

Los TreeModels son tabulares y, como tales, tienen “columnas”, cada una de las cuales está fuertemente tipada, y están representadas en java-gnome por las DataColumn clases.

Mientras que las “columnas” (y sus tipos) deben declararse al crear un TreeModel, las “filas” en un TreeModel son dinámicas; crece a medida que agrega datos al modelo. Una instancia de TreeIter se utiliza para indicar una fila en un TreeModel; estos se usan tanto al agregar nuevas filas como cuando se trata de identificar qué fila se ha seleccionado en una TreeView. Tenga en cuenta que los TreeIters son muy transitorios y solo son válidos siempre que no haya cambiado la estructura del modelo (es decir, agregando otra fila, clasificándola, filtrándola, etc.) de modo que cuando rellenemos un TreeModel tendemos a hacerlo una fila completa a la vez.

Creando una GUI con GtkTreeView en Glade

Dejare un video donde se muestra la forma en que construí la interfaz de usuario con la que se trabajara junto a Java. Dejare un enlace con el código generado en Glade para los impacientes: GUI.glade

En la siguiente tabla se muestra los nombres que se asignaron a los IDs de los Widgets con los que estaremos trabajando.

Widgets ID
WindowwindowID
GtkEntryentryNombreID
GtkEntryentryEdadID
GtkButtonbuttonAnadirID
GtkButtonbuttonActualizarID
GtkTreeViewtreeviewID

Desarrollo de TreeView en Java

Se creara un proyecto en Java donde la clase se llama TabularForm, en el mismo constructor de la clase se iniciara el enlace del widget TreeView creado en Glade para poder construir nuestro TreeModel usando ListStore.

TreeView view;
TreeViewColumn vertical;
TreeIter row;
ListStore listStore;
DataColumnString idColumn, nameColumn, ageColumn;
CellRendererText idText, nameText, ageText;
String captureName, captureAge ;
 
//Constructor
public TabularForm() {
...
//TreeView
view = (TreeView) builder.getObject("treeviewID");
 
/* Construccion del modelo */
listStore = new ListStore(new DataColumnString[]{
 
      idColumn = new DataColumnString(),
      nameColumn = new DataColumnString(),
      ageColumn = new DataColumnString(),
  });
 ...
 
 }

Ahora comienza a crear su vista al crear una instancia de TreeView y luego usarlo para obtener instancias de TreeViewColumn; con el método setTitle() asignara un titulo a la columna:

view.setModel(listStore);
 
vertical = view.appendColumn();
vertical.setTitle("ID");
...
 
vertical = view.appendColumn();
vertical.setTitle("Nombre");
...
 
vertical = view.appendColumn();
vertical.setTitle("Edad");
...

Construiremos un CellRenderer, especificando de qué TreeViewColumn va a formar parte:

vertical = view.appendColumn();
vertical.setTitle("ID");
idText  = new CellRendererText(vertical);
...
 
vertical = view.appendColumn();
vertical.setTitle("Nombre");
nameText = new CellRendererText(vertical);
...
 
vertical = view.appendColumn();
vertical.setTitle("Edad");
ageText = new CellRendererText(vertical);
...

Especificando de dónde vendrán sus datos. Este es el paso que une TreeView y TreeModel.

vertical = view.appendColumn();
vertical.setTitle("ID");
idText  = new CellRendererText(vertical);
idText.setText(idColumn);
 
vertical = view.appendColumn();
vertical.setTitle("Nombre");
nameText = new CellRendererText(vertical);
nameText.setText(nameColumn);
 
vertical = view.appendColumn();
vertical.setTitle("Edad");
ageText = new CellRendererText(vertical);
ageText.setText(ageColumn);

Agregue datos a un TreeModel llamando primero a appendRow() que devuelve un TreeIter que apunta a la nueva fila, y luego usando el setValue() método apropiado para el tipo de datos de cada columna:

row = listStore.appendRow();
listStore.setValue(row, idColumn, String.valueOf(count));
listStore.setValue(row, nameColumn, captureName);
listStore.setValue(row, ageColumn, captureAge);

Dejo el código completo de la clase :

package prog;
 
import java.io.FileNotFoundException;
import java.text.ParseException;
import org.gnome.gdk.Event;
import org.gnome.gtk.Builder;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.ListStore;
import org.gnome.gtk.MessageDialog;
import org.gnome.gtk.MessageType;
import org.gnome.gtk.ResponseType;
import org.gnome.gtk.TreeIter;
import org.gnome.gtk.TreeView;
import org.gnome.gtk.TreeViewColumn;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.Button;
import org.gnome.gtk.CellRendererText;
import org.gnome.gtk.DataColumnString;
import org.gnome.gtk.Button.Clicked;
import org.gnome.gtk.ButtonsType;
import org.gnome.gtk.Entry;
import org.gnome.gtk.Window.DeleteEvent;
 
public class TabularForm {
 
    Builder builder;
    Window window;
    Button buttonAdd, buttonUpdate;
    Entry entryName, entryAge;
    TreeView view;
    TreeViewColumn vertical;
    TreeIter row;
    ListStore listStore;
    DataColumnString idColumn, nameColumn, ageColumn;
    CellRendererText idText, nameText, ageText;
    String captureName, captureAge ;
    int count=0;
 
    public TabularForm() {
 
        try {
 
            builder = new Builder();
            builder.addFromFile("src/GUI/GUI.glade");
 
        } catch (FileNotFoundException | ParseException e) {
 
            e.printStackTrace();
        }
 
        getObjectGlade();
        window.showAll();
 
    }
 
    public void getObjectGlade() {
 
        //Window
        window = (Window) builder.getObject("windowID");
        window.connect(on_windowID_destroy());
 
        //Cajas de texto
        entryName = (Entry) builder.getObject("entryNombreID");
        entryAge = (Entry) builder.getObject("entryEdadID");
 
        //Botones
        buttonAdd = (Button) builder.getObject("buttonAnadirID");
        buttonAdd.connect(on_buttonAnadirID_clicked());
 
        buttonUpdate = (Button) builder.getObject("buttonActualizarID");
        buttonUpdate.connect(on_buttonActualizarID_clicked());
 
        //TreeView
        view = (TreeView) builder.getObject("treeviewID");
 
        /* Construccion del modelo */
        listStore = new ListStore(new DataColumnString[]{
 
                idColumn = new DataColumnString(),
                nameColumn = new DataColumnString(),
                ageColumn = new DataColumnString(),
        });
 
        /*Establezca TreeModel que se usa para obtener datos de origen para este TreeView*/
        view.setModel(listStore);
 
        /*Crear instancias de TreeViewColumn*/
        vertical = view.appendColumn();
        vertical.setTitle("ID");
        idText  = new CellRendererText(vertical);
        idText.setText(idColumn);
 
        vertical = view.appendColumn();
        vertical.setTitle("Nombre");
        vertical.setExpand(true);
        nameText = new CellRendererText(vertical);
        nameText.setText(nameColumn);
 
        vertical = view.appendColumn();
        vertical.setTitle("Edad");
        ageText = new CellRendererText(vertical);
        ageText.setText(ageColumn);
 
    }
 
    private DeleteEvent on_windowID_destroy() {
        return new Window.DeleteEvent() {
 
            @Override
            public boolean onDeleteEvent(Widget arg0, Event arg1) {
                Gtk.mainQuit();
                return false;
            }
        };
 
    }
 
    private Clicked on_buttonAnadirID_clicked() {
        return new Button.Clicked() {
 
            @Override
            public void onClicked(Button arg0) {
 
                //Acciones del boton Agregar
 
                captureName=entryName.getText().toUpperCase();
                captureAge=entryAge.getText();
 
                entryName.setText("");
                entryAge.setText("");
 
                count++; //Aunmenta el contador cada ves que se agrega un nombre
 
            }
        };
 
    }
 
    private Clicked on_buttonActualizarID_clicked() {
        return new Button.Clicked() {
 
            @Override
            public void onClicked(Button arg0) {
 
                //Acciones del boton Actualizar
 
                MessageDialog dialog = new MessageDialog(window, true, MessageType.WARNING, ButtonsType.CLOSE,"Se han agregado nuevos valores");
                dialog.setSecondaryText("La tabla tiene nuevos valores, presione el boton cerrar para continuar");
 
                // Oculta el dialogo
                ResponseType choice = dialog.run();
                if (choice == ResponseType.CLOSE) {
                    dialog.hide();
 
                }
 
                /* Agregue datos a TreeModel usando appendRow() que devuelve un TreeIter
                 * que apunta a la nueva fila, y luego usando el setValue()
                 * apropiado para el tipo de datos de cada columna
                 * */
 
                row = listStore.appendRow();
                listStore.setValue(row, idColumn, String.valueOf(count));
                listStore.setValue(row, nameColumn, captureName);
                listStore.setValue(row, ageColumn, captureAge);
 
            }
        };
 
    }
 
    public static void main(String[] args) {
 
        Gtk.init(args);
        new TabularForm();
        Gtk.main();
 
    }
 
}

Video mostrando la aplicación ya funcionando:

Referencias

Usar GtkHeaderBar con Glade

Dentro de los patrones de diseño de Gnome se encuentran las Header Bars o Barra de encabezados, son un elemento horizontal que se ponen en la parte superior de la ventana de una aplicación, se pueden observar en las principales aplicaciones deSigue leyendo “Usar GtkHeaderBar con Glade”

Java: Problemas de recursividad con solución

He estado viendo el tema de la recursividad  y como aplicarlo en la programación, dejare algunos ejercicios ya resueltos aplicando la recursividad con Java.

  • Crea un programa donde se pida en el principal la tabla de multiplicar deseada, en un método recursivo generar la tabla de multiplicar. Se multiplicara hasta querer llegar al numero 12 como resultado. El formato de salida es el siguiente:
    5 x 1 = 5
    5 x 2 = 10
import java.util.Scanner;

public class Main {

	@SuppressWarnings({ "resource" })
	public static void main(String[] args) {

		Scanner reading = new Scanner(System.in);
		int num=0;

		System.out.print("Pida la tabla de multiplicar: ");
		num=reading.nextInt();
		tableMultiplication(num,10);

	}

    public static void tableMultiplication(int TABLE, int LENGTH){

    	if (LENGTH>1) {
    		tableMultiplication(TABLE,LENGTH-1);
    	}

    	if ((TABLE*LENGTH)<=12) {

    		System.out.printf("%d x %d = %d \n",TABLE,LENGTH,(TABLE*LENGTH));
    	}
    }

}
  • Crea un programa donde ingreses 10 nombres de ciudades, y en un método recursivo muestra las ciudades al reves (es decir del ultimo al primero)
import java.util.Scanner;

public class Main {

	static String country[] = new String[10];

	public static void main(String[] args) {

		@SuppressWarnings("resource")
		Scanner reading = new Scanner(System.in);

		for (int i = 0; i < country.length; i++) {

			System.out.printf("Ingrese el nombre de la ciudad #%d: ",(i+1));
			country[i]=reading.nextLine();
		}

		//Llamada al metodo recursivo
		System.out.println("\n");
		outputCountry(country.length-1);
	}

	public static void outputCountry(int LENGTH) {

		if(LENGTH==0) { //Termina cuando country[] llegue a la posicion 0 

			System.out.printf("Ciudad #%d : %s  \n",(LENGTH+1),country[LENGTH].toUpperCase());

		}else {

			System.out.printf("Ciudad #%d : %s \t*\n",(LENGTH+1),country[LENGTH].toUpperCase());
			outputCountry(LENGTH-1);
		}

	}

}
  • Crea un programa donde ingreses en un método recursivo la captura de numeros, esto son almacenados en un arreglo, la recursividad termina cuando el usuario ingrese el numero -1, al termino del mismo, muestra los valores capturados en el mismo método
import java.util.ArrayList;
import java.util.Scanner;
 
public class Main {
 
    static Scanner reading = new Scanner(System.in);
    static ArrayList number = new ArrayList();
    static boolean flag=true;
    static int count=0;
 
    public static void main(String[] args) {
 
        captureNumbers();
 
    }
 
    public static void captureNumbers() {
 
        int value=0;
 
        if(flag) {
 
            System.out.print("Ingrese un numero: ");
            value=reading.nextInt();
 
            if(value==-1) {
 
                //Temina de capturar datos en el Array
                flag=false;
                System.out.println("\n[VALORES CAPTURADOS]\n");
                captureNumbers();
 
            }else {
 
                //Se agrega el numero capturado al ArrayList
                number.add(value);
 
                //Se vuelve a llamar a si mismo la funcion
                captureNumbers();
            }
 
        }else {
 
            if(count==number.size()) {
 
                //Test
                System.out.println("\n [ Termino ] ");
                System.out.println("El contador es: "+count);
                System.out.println("El arreglo es: "+number.size());
 
            }else {
 
                //System.out.println("\n[VALORES CAPTURADOS]\n");
                System.out.println("Numero #"+count+" = "+number.get(count));
                count++;
                captureNumbers();
 
            }
        }
 
    }
}
  • Crea un programa donde se pida el nombre de una persona en el principal y en un método recursivo mostrarlo de forma inversa.
import java.util.Scanner;
 
public class Main {
 
    static char[] charName=null;
 
    public static void main(String[] args) {
 
        @SuppressWarnings("resource")
        Scanner reading = new Scanner(System.in);
 
        System.out.print("Ingrese su nombre: ");
        String name = reading.nextLine();
        charName = name.toCharArray();
 
        System.out.println("\n[ NOMBRE AL REVES ]");
        nameReverse(charName.length-1);
 
    }
 
    public static void nameReverse(int LENGTH) {
 
        if(LENGTH==0) {
 
            System.out.print(charName[LENGTH]+".");
 
        }else {
 
            System.out.print(charName[LENGTH]);
            nameReverse(LENGTH-1);
        }
 
    }
 
}
  • Crear un programa utilizando la recursividad para obtener la suma total de números, estos son almacenados en un acumulador, mostrar la suma total cuando el usuario capture el valor de 0.
import java.util.Scanner;
 
public class Main {
 
    static Scanner reading = new Scanner(System.in);
 
    public static void main(String[] args) {
 
        int accumulator=0;
        int count=1;
        captureRecursive(accumulator, count);
 
    }
 
    public static void captureRecursive(int ACCUMULATOR, int COUNT) {
 
        System.out.printf("Ingrese el #%d : ",COUNT);
        int num=reading.nextInt();
 
        if(num==0) {
 
            System.out.println("\nSe ingreso cero\n"
                    + "Suma total: "+ACCUMULATOR+"\n"
                            + "Fin!.");
 
        }else {
 
            ACCUMULATOR+=num;
            captureRecursive(ACCUMULATOR,COUNT+1);
        }
 
    }
 
}

Montando un servidor SIP con Kamailio en Fedora Server 27

En este apartado se pretende ser una guía de una instalación básica de un servidor SIP con Kamailio bajo la distribución de Fedora Server 27,  por supuesto que también funciona para la versión Workstation. Si pretendes instalar otra distribución Kamailio ofrece algunos paquetes y el código fuente para usarlo prácticamente el cualquier entorno GNU/Linux y Unix. Dando hincapié de que es Kamailio como se describe en el sitio oficial:

Kamailio is an Open Source SIP Server released under GPL, able to handle thousands of call setups per second. Kamailio can be used to build large platforms for VoIP and realtime communications – presence, WebRTC, Instant messaging and other applications.

Como se había indicado sera una guiá para una instalación básica de Kamailio, este contenido realmente sera una copia descarada de la documentación que ofrece Kamailio para instalarlo en Debian, así que solamente se ha hecho una adaptación para ser instalado en Fedora Server 27.

Comandos de instalación

Comencemos agregando el repositorio oficial, abriremos una terminal y escribiremos lo siguiente:

# dnf config-manager --add-repo=http://download.opensuse.org/repositories/home:/kamailio:/v5.1.x-rpms/Fedora_27/home:kamailio:v5.1.x-rpms.repo

Refrescamos los repositorios:

# dnf check-update

En seguida instalaremos Kamailio y aparte un modulo para trabajar con MariaDB, tipeamos el siguiente comando para instalar los paquetes necesarios:

# sudo dnf install kamailio-websocket kamailio kamailio-ims kamailio-mysql mariadb mariadb-server -y

Vamos ha indicar que el servidor de base de datos MariaDB inicie en cada arranque del sistema pero también lo vamos a iniciar en este momento para trabajar con el:

# systemctl enable mariadb; systemctl start mariadb

Estando en marcha MariaDB ahora iniciamos el asistente:

# mysql_secure_installation

Asignaremos una contraseña para el gestor de base de datos

Set root password? [Y/n] y
Remove anonymous users? [Y/n] y
Disallow root login remotely? [Y/n] y
Remove test database and access to it? [Y/n] y
Reload privilege tables now? [Y/n] y

Archivos de configuración

Los archivos de configuración están ubicados en el directorio /etc/kamailio/.

kamctlrc

El /etc/kamailio/kamctlrc es el archivo de configuración para las herramientas kamctl y kamdbctl. Buscaremos editaremos SIP_DOMAIN donde agregaremos el nombre de dominio o la dirección IP del servidor

Establezca también el DBENGINE el motor de base de datos, en este caso sera MYSQL. Muy importantes son las contraseñas para conectarse MySQL al servidor, respectivamente DBRWPWDBROPW. Por defecto, sus valores son kamailiorwkamailioro. Debe cambiarlos antes de ejecutarlos kamdbctl create(el paso detalla la sección Crear base de datos ).

SIP_DOMAIN=172.24.1.52	#IP del servidor
DBENGINE=MYSQL 		#La base de datos que se trabajara

kamailio.cfg

El /etc/kamailio/kamailio.cfg es el archivo de configuración para kamailio. Edítelo para habilitar algunas de las funciones que se incluyen con él.

Para habilitar el uso del MySQL back-end del servidor, la autenticación del usuario y la ubicación persistente del usuario, agregue después de la primera línea:

#!define WITH_MYSQL
#!define WITH_AUTH
#!define WITH_USRLOCDB

Crear base de datos

Para crear la estructura de la base de datos que necesita Kamailio, ejecute:

# kamdbctl create

El nombre de la base de datos creado en MySQL es kamailio . Se crearon dos usuarios de acceso al servidor MySQL

  • kamailio – (con la contraseña establecida por DBRWPW en kamctlrc) – usuario que tiene plenos derechos de acceso a la base de datos kamailio
  • kamailioro – (con la contraseña establecida por DBROPW en kamctlrc) – usuario que tiene derechos de acceso de solo lectura a la base de datos kamailio

El acceso para los dos usuarios está restringido a localhost , pero como se indicó anteriormente, se recomienda cambiar sus contraseñas predeterminadas.

Scripts de inicio

Primeramente reiniciaremos Fedora Server 27:

# reboot

Iniciamos Kamailio:

# service kamailio start
Redirecting to /bin/systemctl start kamailio.service  

Habilitamos el puerto para que se pueda comunicar fuera del host o de Internet:

# firewall-cmd --permanent --add-service=sip; firewall-cmd --reload

Agregar suscriptores

Para agregar suscriptores (usuarios), puede usar el comando kamctl :

# kamctl add 2018001 secret001

Luego puede configurar su teléfono para que se registre en Kamailio usando el nombre de usuario y la contraseña establecidos en el comando anterior.

Mostrar suscriptores

Puedes ver los suscriptores registrado en Kamailio desplegando la tabla subscriber de la base de datos tipeando el siguiente comando:

# kamctl db show subscriber
which: no gdb in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/)
+----+----------+--------------+-----------+----------------------------------+----------------------------------+---------------+------+
| id | username | domain       | password  | ha1                              | ha1b                             | email_address | rpid |
+----+----------+--------------+-----------+----------------------------------+----------------------------------+---------------+------+
|  1 | 2018001  | 172.24.1.52  | secret001 | 9feb5892a47453494ee3629a4c28dbb0 | bfe55e62718d5964daf72adc42fb2c4a | NULL          | NULL |
+----+----------+--------------+-----------+----------------------------------+----------------------------------+---------------+------+

En el siguiente video se ejemplifica el proceso de registro de usuarios para luego realizar una comunicación VoIP entre dispositivos.

Referencia:

Instalar Glade 3.21.0 con Flatpak

Glade se ha actualizado de la versión 3.20.x a la versión mas reciente al día de hoy 3.21.0, a sufrido varias mejoras, como la integración de GtkGLArea, soporte para la librería WebKit2GTK+, pero el cambio mas notable a sido su interfaz, la Sigue leyendo “Instalar Glade 3.21.0 con Flatpak”

Realiza copias de seguridad cifradas en GNU/Linux con Déjà Dup

Hacer copias de seguridad en una buena practica para preservar la información valiosa en caso de que la información original llegara a ser comprometida, pero no están seguro si no se lleva bien esta practica usando métodos de cifrado, si losSigue leyendo “Realiza copias de seguridad cifradas en GNU/Linux con Déjà Dup”

Crear programas en Java usando GUI generados en Glade

En algún momento puedes verte en la necesidad, por interés ó por la cuestión que puedas tener el desarrollar un programa con interfaz gráfica en entornos GNU/Linux, por compatibilidad en la mayoría de las distribuciones aparece GTK+, anteriormente me había tocado hablar de como crear aplicaciones Java basadas en GTK+, si… eso fue hace bastante tiempo, pero para aprovechar ese tiempo y las lineas que te toma el tener que programa dentro de la misma clase el posicionado de una caja o botón se puede reducir realmente el tiempo de desarrollo de programas con interfaz gráfica GTK+ usando el programa por excelencia a la fecha de hoy en la que se escribió esta entrada es haciendo uso de Galde. Una descripción de que es Glade a como lo explican en el sitio oficial:

Glade is a RAD tool to enable quick & easy development of user interfaces for the GTK+ toolkit and the GNOME desktop environment.

The user interfaces designed in Glade are saved as XML, and by using the GtkBuilder GTK+ object these can be loaded by applications dynamically as needed.

He preparado un proyecto en el cual se vera el uso superficial de Glade y explicativo de como usar el archivo generado con Java.

Estructura del proyecto:

  • src
    • gui
      • app.glade
    • prog
      • Constants.java
      • Suma.java

Para empezar a tirar código es necesario tener listo preparativos para empezar programar. Habrá que instalar unos los siguientes paquetes:

  • java-gnome (API GTK para Java )
  • java-gnome-javadoc (Documentación)
  • Glade (Desarrollo rápido de aplicaciones para GTK+)

Ya habiendo terminado de instalar todo, es momento de abrir Glade. En esta practica he hecho una plantilla, puedes ver el código generado dando click en app.glade. Habiendo descargado el archivo, en Glade nos dirigimos ha Archivo>Abrir y buscamos el archivo descargado .glade para cargar la interfaz.

Captura de pantalla de 2017-09-25 00-10-54
Archivo app.glade abierto desde Glade

El diseño de la GUI, trata de ser simple, podemos observar que varios widgets tienen asignado un ID,  son los  widgets con los que estaremos trabajando y los ID’s tomaran importancia en el código, también puedes modificar el nombre del ID de los botones y cajas de texto en el aparatado de Propiedades, justo donde indica la flecha roja en la siguiente imagen.

Captura de pantalla de 2017-10-01 02-26-34

Dejaremos los valores como tal si crees que te puede confundir mientras avanzas en esta practica.

A continuación dejare representados en una tabla los Widgets con sus respectivos ID:

Widgets ID
WindowId_Suma
GtkEntrytextNum1
GtkEntrytextNum2
GtkEntrytextResult
GtkButtonbotonSuma
GtkButtonbotonLimpiar

El archivo es solo la apariencia, una carroza sin motor pero haremos que funcione usando a Java como nuestro aliado. Utilizaremos la librería java-gnome previamente instalada, en la mayoría de las distribuciones se debe de encontrar en el directorio /usr/lib64/java-gnome/gtk.jar, ahora seria añadir el archivo gtk.jar a un IDE de preferencia.

Ya teniendo preparado el entorno para programar, pasare creando un interface nombrándola Constants donde obtendrá valores constantes de los directorios que usaremos mas adelante:

package prog;
 
public interface Constants {
 
String HOME = System.getProperty("user.home");
String FOLDER_DIR=HOME+"/SumaGlade/gui";
 
}

En la interface se almaceno en la primera variable HOME, el directorio de usuario donde ejecutemos nuestro programa, en la siguiente linea almacenamos en la variable FOLDER_DIR otro futuro directorio que estaremos creando en el directorio del usuario.

La siguiente clase nombrada Suma, utilizara las siguientes clases que proporciona la API:

package prog;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.ParseException;
import org.gnome.gdk.Event;
import org.gnome.gtk.Builder;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.Window.DeleteEvent;
import org.gnome.gtk.Entry;
import org.gnome.gtk.Button;
import org.gnome.gtk.Button.Clicked;
 
public class Suma implements Constants{
 
    public static Builder builder;
    public static Window window;
    public Entry Text_num1;
    public Entry Text_num2;
    public Entry Text_result;
    public Button bttn_sum;
    public Button buttn_clean;
    public Button bttn_exit;
    public Window w_exit;
 
    public Suma(){  
 
        copyResource();
 
        try {
            builder = new Builder();
            builder.addFromFile(FOLDER_DIR+"/app.glade");
 
        } catch (FileNotFoundException e) {
            System.err.println(""+e.getMessage());
 
        } catch (ParseException e) {
            System.err.println(""+e.getMessage());
        }
 
        iniciarObjectos();
        window.showAll();
 
    }//Fin del constructor
 
    public void iniciarObjectos() {
        //Vamos a enlazar los los objectos correspondientes a los ID de los Widgets
 
        //windows
        window =(Window) builder.getObject("Id_Suma");
 
        //Cajas de texto
        Text_num1 = (Entry) builder.getObject("textNum1");
        Text_num2 = (Entry) builder.getObject("textNum2");
        Text_result = (Entry) builder.getObject("textResult");
 
        //Botones
        bttn_sum = (Button) builder.getObject("botonSuma");
        bttn_sum.connect(on_botonSuma_clicked());
 
        buttn_clean = (Button) builder.getObject("botonLimpiar");
        buttn_clean.connect(on_botonLimpiar_clicked());
 
        bttn_exit = (Button) builder.getObject("botonSalir");
        bttn_exit.connect(on_botonSalir_clicked());
 
        w_exit = (Window)builder.getObject("Id_Suma");
        w_exit.connect(on_calculadora_destroy());
 
    }
 
    private Clicked on_botonSuma_clicked() {
        return new Button.Clicked() {
 
            @Override
            public void onClicked(Button arg0) {
 
                //Se captura los valores ingresados en las cajas de texto
                int num1= Integer.parseInt(Text_num1.getText());
                int num2= Integer.parseInt(Text_num2.getText());
                int suma= num1+num2;
 
                //La operacion de suma de mostrara en la caja de texto "textResult"
                Text_result.setText(Integer.toString(suma));
            }
        };
    }
 
    private Clicked on_botonLimpiar_clicked(){
        return new Button.Clicked() {
 
            @Override
            public void onClicked(Button arg0) {
 
                Text_num1.setText("");
                Text_num2.setText("");
                Text_result.setText("");
 
            }
        };
    }
 
    private Clicked on_botonSalir_clicked() {
        return new Button.Clicked() {
 
            @Override
            public void onClicked(Button arg0) {
                Gtk.mainQuit();
 
            }
        };
 
    }
 
    private DeleteEvent on_calculadora_destroy() {
        return new Window.DeleteEvent() {
 
            @Override
            public boolean onDeleteEvent(Widget arg0, Event arg1) {
                Gtk.mainQuit();
                return false;
            }
        };
    }
 
    public void copyResource() {
 
        File folder = new File(FOLDER_DIR);
        folder.mkdirs();
 
        try {
 
            InputStream input=getClass().getResourceAsStream("/gui/app.glade");
            OutputStream output= new FileOutputStream(FOLDER_DIR+"/app.glade");
            byte [] buffer = new byte[1024];
            int bytesRead;
 
              while ((bytesRead = input.read(buffer,0,1024)) != -1) {
 
                    output.write(buffer, 0, bytesRead);
                }
 
              output.close();
              input.close();
 
         } catch(IOException e) {
            System.err.println(""+e.getMessage());
         }
      }
 
    public static void main(String[] args) {
        System.out.println("Run!");
        Gtk.init(args);
        new Suma();
        Gtk.main();
 
    }
 
}

En la clase Suma podemos ver como se inicia el método main para crear un programa típico de java-gnome iniciando con Gtk.init(args); y finalizando con Gtk.main(); y en medio se hace el llamada al constructor de la misma clase, el constructor llama al método copyResource(), este método hará que nuestro programa se pueda portar fácilmente a otros equipos, Porque?, anteriormente en otra entrada ya había publicado la utilidad que se le puede dar a este método que trata de  copiar y pegar un archivo que esta dentro de un JAR, después de haberse ejecutado el método copyResource() tendremos nuestro archivo Glade en el directorio $HOME/SumaGlade/gui/app.glade.

Dentro del mismo constructor se encuentra un try-catch, se crea un objecto de la clase Builder para usar el método addFromFile que nos ayudara a cargar la interfaz de usuario generado por Glade, al salir del try-catch se manda a llamar al método iniciarObjectos() que realizara la comunicación de los objectos correspondientes a su ID.

Finaliza el constructor con el lanzamiento de la interfaz de usuario invocando la linea window.showAll();. Lo que queda de la clase son métodos que corresponden a las funciones que realizara cuando el usuario interactue con el programa (Sumar, Limpiar y Cerrar).

En realidad no soy experto en el tema de ser un developer, me gusta la programación, bastante diría yo,  esto para mi a sido un reto, no de esos difíciles si no del hecho de aprende algo fuera de lo común, buscando en Internet sobre como desarrollar aplicaciones para GNU/Linux con interfaz gráfica GTK+ es realmente escasa, lo mas popular que puede encontrar es usando lenguajes como C, C# y Python, en Java la información es muy anticuada al igual que los videotutoriales pixeleado por el tiempo, aun mostrado el uso de libglade o lo mas que enseñan es a como instalar Glade XD, mi intención no era desahogarme con ustedes, solo es para que se animen a desarrollar en Linux, y a mostrar al mundo sus trabajos, sera de utilidad para muchos, bueno es  hora de finalizar esta entrada y recuerden, Si se puede imaginar, se puede programar.

Realizar un ataque Evil Twin para capturar claves Wi-Fi con Wifiphisher

Crear un escenario ideal para obtener la contraseña Wi-Fi con protocolos de seguridad WPA/WPA2  usando un ataque Evil Twin no requiere demasiados recursos y tiempo como llevar acabo los clásicos ataque a fuerza bruta o por diccionario.Sigue leyendo “Realizar un ataque Evil Twin para capturar claves Wi-Fi con Wifiphisher”

Copiar y pegar un archivo que esta dentro de un JAR

Habrán ocasiones en que sea necesario hacer un copy-paste de algún archivo como un pdf, .txt, una imagen, etc, etc, que este localizado dentro del mismo JAR por cuestiones que puedes poner. Poniendo un ejemplo:

Supongamos que tenemos una imagen dentro de nuestro Resource.

  • Proyecto
    • src
    • Imagenes
      • imagen-original.jpg

Y por x o y razón queremos que esa imagen se localice en tal parte de nuestro directorio personal, que tal en /home/nameUser/Copias el siguiente método es una muestra de como llevar acabo esa tarea.

Clases usadas:

public void copyResource() {
 
    String home=System.getProperty("user.home");
    File folder = new File(home+"/Copias");
    folder.mkdirs();
 
    try {
 
        InputStream input=getClass().getResourceAsStream("/Imagenes/imagen-original.jpg");
        OutputStream output= new FileOutputStream(folder+"/imagen-copia.jpg");
        byte [] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = input.read(buffer,0,1024)) != -1) {
 
            output.write(buffer, 0, bytesRead);
        }
 
        output.close();
        input.close();
 
    }
    catch(Exception e) {
        e.printStackTrace();
 
    }
 
}

Referencia:

A %d blogueros les gusta esto: