7.10 CREACIÓN DE UN PROCESADOR DE TEXTOS

 

Bienvenidos a todos, ¿qué tal? Este post va a consistir en la creación de un procesador de textos, no va a ser como LibreOffice Writer o Microsoft Word va a ser más básico pero en el que apliquemos conceptos ya aprendidos. En este procesador va a ser muy rudimentario pero vosotros podéis añadir nuevas funcionalidades,  cambiar la interfaz, etc., y si luego encima lo queréis compartir pues vamos, mejor de lo mejor. Así que vamos a empezar con el proyecto.

El procesador de texto va a consistir en la parte superior tres menús: Fuente Estilo Tamaño con los submenús respectivos: Arial Courier y Verdana Cursiva Negrita 12 16 18 20 En parte inferior un área de texto con el cursor parpadeando para poder escribir. Escribimos cualquier frase y podemos cambiar la fuente, el estilo, el tamaño…

Sería recomendable antes de que siguierais leyendo probad a realizarlo vosotros solos, no obstante, explico paso a paso la creación de este procesador de texto que a su vez lo iremos mejorando.

Para empezar nos creamos un proyecto nuevo en Java al que vamos a llamar ProcesadorTexto, nos creamos un paquete prtxt, dentro de este paquete nos creamos la clase Procesador que va a contener el siguiente código:

package prtxt;

 

import javax.swing.JFrame;

import javax.swing.JPanel;

 

public class Procesador {

 

      public static void main(String[] args) {

           

            MenuProcesador mimenu = new MenuProcesador();

           

            mimenu.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

 

      }

 

}

class MenuProcesador extends JFrame {

     

      public MenuProcesador() {

           

            setBounds(500,300,550,400);

           

            LaminaProcesador milamina = new LaminaProcesador();

           

            add(milamina);

           

            setVisible(true);

      }

     

}

class LaminaProcesador extends JPanel{

     

      public LaminaProcesador() {

           

           

      }

}

Lo primero hay que fijarnos en la distribución en la parte superior va a ir la barra de menús y en la parte inferior el área de texto. En este caso vamos a utilizar el setLayout BorderLayout. En el constructor de la lámina nos creamos la disposición:

      public LaminaProcesador() {

           

            setLayout(new BorderLayout());

      }

Nos creamos una segunda lámina:

JPanel LaminaMenu  = new JPanel();

El siguiente paso es crear la barra de menús :

JMenuBar mibarra = new JMenuBar();

Tenemos que determinar que elementos va a contener esta barra, creamos los menús:

            JMenu fuente = new JMenu("Fuente");

           

            JMenu estilo = new JMenu("Estilo");

           

            JMenu tamano = new JMenu("Tamaño");

Agregamos los menús a la barra de menús:

            mibarra.add(fuente);

           

            mibarra.add(estilo);

           

            mibarra.add(tamano);

Tenemos que añadir la barra de menús a la lámina que va en la parte superior, esa lámina es la segunda lámina.

LaminaMenu.add(mibarra);

Tenemos que indicar que la segunda lámina con su correspondiente barra de menús va en la parte superior de la lámina principal:

add(LaminaMenu, BorderLayout.NORTH);

Lo siguiente sería crear los elementos que cuelgan de los menús, es decir, los submenús. Después de los elementos JMenu vamos a crearnos los submenús para ello utilizamos la clase JMenuItem:

            JMenuItem arial = new JMenuItem("Arial");

           

            JMenuItem courier = new JMenuItem("Courier");

           

            JMenuItem verdana = new JMenuItem("Verdana");

Posteriormente añadimos los submenús al menú:

            fuente.add(arial);

           

            fuente.add(courier);

           

            fuente.add(verdana);

Y haríamos lo mismo con los submenús del menú Edición y el menú Tamaño:

     

            JMenuItem negrita = new JMenuItem("Negrita");

           

            JMenuItem cursiva = new JMenuItem("Cursiva");

           

            estilo.add(negrita);

           

            estilo.add(cursiva);

           

           

            JMenuItem tam_12 = new JMenuItem("12");

           

            JMenuItem tam_16 = new JMenuItem("16");

           

            JMenuItem tam_20 = new JMenuItem("20");

           

            JMenuItem tam_24 = new JMenuItem("24");

           

     

            tamano.add(tam_12);

           

            tamano.add(tam_16);

           

            tamano.add(tam_20);

           

            tamano.add(tam_24);

Con esto ya tendríamos la barra de menús:



El siguiente paso es crear el área de texto y para ello vamos a utilizar la clase JTextPane que nos permite añadir barras de desplazamiento y modificar texto a diferencia de la clase JTextArea.

Nos situamos después de la línea de código:

add(LaminaMenu, BorderLayout.NORTH);

Creamos un objeto de tipo JTextPane y lo ubicamos en la parte central de la lámina principal:

JTextPane miarea = new JTextPane();

           

add(miarea, BorderLayout.CENTER);

Con esto ya tendríamos el área de texto creada donde poder escribir:



Ahora tenemos que indicar a cada uno de los elementos que cuelgan de los menús tenemos que ponerlos a la escucha de un evento de tipo actionListener para que cuando pulsemos en uno de los elementos con el ratón vaya cambiando las características del texto que hay escrito. Vamos a empezar con este elemento:

JMenuItem courier = new JMenuItem("Courier");

De forma que al pulsar el submenú Courier se desencadene el evento y el evento va a ser que el texto cambie el tipo de letra a Courier.

Nos creamos una clase interna que gestione los eventos para el elemento Courier. Después del constructor de la lámina nos creamos la clase:

      private class GestionaMenus implements ActionListener {

 

            @Override

            public void actionPerformed(ActionEvent e) {

                  // TODO Auto-generated method stub

                 

            }

      }

Dentro del método actionPerformed vamos a programar el evento del elemento Courier.

      private class GestionaMenus implements ActionListener {

 

            @Override

            public void actionPerformed(ActionEvent e) {

                 

                  miarea.setFont(new Font("Courier", Font.PLAIN, 12 ));

                 

                 

            }

      }

En el constructor de la lámina después de la línea de código hemos declarado el elemento Courier instanciamos el elemento:

            GestionaMenus tipo_letra = new GestionaMenus();

           

            courier.add(courier);

En lugar de utilizar la clase interna podemos utilizar una clase anónima de la siguiente forma:

            courier.addActionListener(new ActionListener() {

                  @Override

                  public void actionPerformed(ActionEvent e) {

                       

                        miarea.setFont(new Font("Courier", Font.PLAIN, 12 ));

                            

                  }

 

            });

Eliminamos la clase interna.

Con los siguientes elementos Arial y Verdana hacemos lo mismo, creamos una clase anónima para cada uno de ellos:

            JMenuItem arial = new JMenuItem("Arial");

           

            arial.addActionListener(new ActionListener() { //Clase anónima. Nos crea el evento para convertir el tipo de letra a Courier

                  @Override

                  public void actionPerformed(ActionEvent e) {

                       

                        miarea.setFont(new Font("Arial", Font.PLAIN, 12 ));

                            

                  }

 

            });

            JMenuItem verdana = new JMenuItem("Verdana");

           

            verdana.addActionListener(new ActionListener() { //Clase anónima. Nos crea el evento para convertir el tipo de letra a Courier

                  @Override

                  public void actionPerformed(ActionEvent e) {

                       

                        miarea.setFont(new Font("Verdana", Font.PLAIN, 12 ));

                            

                  }

 

            });

Sin embargo, tal y como tenemos planteado el código si tenemos que crear una clase interna por cada uno de los elementos que nos quedan nos va a quedar un código muy extenso, para evitar que haya tanto código se podía plantear de otra forma.

Lo primero sería eliminar todos los submenús que hemos creado en el constructor de la lámina dejarlo de la siguiente forma:

public LaminaProcesador() {

           

            setLayout(new BorderLayout());

           

            JPanel LaminaMenu  = new JPanel();

           

            JMenuBar mibarra = new JMenuBar();

           

            //Creación de los menús

            JMenu fuente = new JMenu("Fuente");

           

            JMenu estilo = new JMenu("Estilo");

           

            JMenu tamano = new JMenu("Tamaño");

           

            mibarra.add(fuente);

           

            mibarra.add(estilo);

           

            mibarra.add(tamano);

           

            LaminaMenu.add(mibarra);

           

            add(LaminaMenu, BorderLayout.NORTH);

           

            miarea = new JTextPane();         

            add(miarea, BorderLayout.CENTER);

           

      }

Declarar las variables de clase de los menús van al final de la última llave de cierre de código:

      JTextPane miarea; //Objeto del área de texto

     

      JMenu fuente, estilo, tamano; //creamos los menús

     

      Font letras;

Y en el constructor de la lámina ya no es necesario declarar los menús:

            JMenu fuente = new JMenu("Fuente");

           

            JMenu estilo = new JMenu("Estilo");

           

            JMenu tamano = new JMenu("Tamaño");

Luego nos creamos un método que ponga los elementos a la escucha y a la misma vez construir los elementos, el método lo creamos después del constructor de la lámina:

      public void ConfiguraMenu (String rotulo, String menu, String tipo_letra, int estilos, int tam) {

           

           

      }

A este método le pasamos una serie de parámetros: rotulo que va a servir para especificar el texto que va a tener el menú que estemos construyendo en cada momento, por ejemplo, si es Arial, Courier, si va a tener negrita o cursiva, si el tamaño va a tener 20 o 25, el segundo parámetro Menu se va a encargar de especificar si el elemento que estamos creando en cada momento a que menú tiene que ir, por ejemplo, si al menú fuente, al menú estilos, el tercer parámetro tipo_letra se va a encargar de los elementos que cuelgan del menú Fuente especificar el tipo de letra, el cuarto parámetro estilos especificar si el texto va a ir en negrita o en cursiva y el último parámetro especificiar el tamaño del texto si va a tener 12, 20…

Con esto empezamos a crearnos los submenús instanciamos la clase JMenuItem :

JMenuItem submenus = new JMenuItem(rotulo);

Mediante un condicional especificamos donde han de ir los elementos:

            JMenuItem submenus = new JMenuItem(rotulo);

           

            if(menu=="fuente") {

                 

                  fuente.add(submenus);

            }else if(menu=="estilo") {

                 

                  estilo.add(submenus);

            }else if(menu=="tamano") {

                 

                  tamano.add(submenus);

            }

Ahora en el constructor de la lámina después de la creación de los menús creamos cada uno de los JMenuItems

            ConfiguraMenu("Arial", "fuente", "", 1,1);

           

            ConfiguraMenu("Courier", "fuente", "", 1,1);

           

            ConfiguraMenu("Verdana", "fuente", "", 1,1);

Para los estilos:

            ConfiguraMenu("Negrita", "estilo", "", 1,1);

           

            ConfiguraMenu("Cursiva", "estilo", "", 1,1);

Para el tamaño:

ConfiguraMenu("12", "tamano", "", 1,1);

           

            ConfiguraMenu("16", "tamano", "", 1,1);

           

            ConfiguraMenu("20", "tamano", "", 1,1);

           

            ConfiguraMenu("24", "tamano", "", 1,1);

Con esto ya tendríamos creamos todos los submenús.

Creamos una clase interna que gestione los eventos estos submenús, después de la llave de cierre del método creamos la clase:

      private class GestionaEventos implements ActionListener{

 

            @Override

            public void actionPerformed(ActionEvent e) {

                  // TODO Auto-generated method stub

                 

            }

           

           

      }

Dentro del método le vamos a indicar que cambie el tipo de letra:

            public void actionPerformed(ActionEvent e) {

                 

                  miarea.setFont(new Font("Arial", Font.BOLD, 14));

                 

            }

Sin embargo, aquí hay un inconveniente ya que al constructor de setFont le hemos pasado valores fijos de forma que si lo dejamos así cuando pulsemos en cualquier submenú nos va a poner el texto en Arial, negrita y un tamaño de 14. De alguna forma tenemos que sustituir estos valores por tres variables que vayan cambiando dependiente del submenú que seleccionemos. Para ello dentro de la clase interna antes del método nos creamos las variables:

private class GestionaEventos implements ActionListener{

           

            String tipo_texto, menu;

           

            int estilo_letra, tamano_letra;

 

            @Override

            public void actionPerformed(ActionEvent e) {

                 

                  miarea.setFont(new Font("Arial", Font.BOLD, 14));

                 

            }

           

           

      }

Sustituimos los valores fijos por las variables:

public void actionPerformed(ActionEvent e) {

                 

                  miarea.setFont(new Font(tipo_texto, estilo_letra, tamano_letra));

                 

            }

Tenemos que almacenar estas variables el tipo de letra, el estilo, el tamaño del menú correspondiente, es decir, necesitamos pasar los valores de la clase padre a la clase hijo, para ello vamos a utilizar el constructor de la clase interna que gestiona eventos. Después de las variables nos creamos el constructor.

            GestionaEventos(String elemento, String texto2, int estilo2, int tam_letra){

                 

                 

            }

Al constructor le pasamos una serie de parámetros, el primer parámetro elemento que va a detectar el submenú que hemos pulsado, el segundo parámetro texto2 va almacenar el texto del botón, otro parámetro estilo2 que va almacenar el estilo que hayamos pulsado y otro parámetro tam_letra que almacene el tamaño de la letra.

En definitiva, este constructor va a detectar que submenú hemos pulsado, evidentemente para pasar los parámetros al constructor tenemos que hacer la llamada en la clase padre a este constructor esto lo vamos a hacer en cuanto instanciemos la clase GestionaEventos que es la encargada de gestionar los eventos, dentro del constructor vamos a darle valores a las variables:

            GestionaEventos(String elemento, String texto2, int estilo2, int tam_letra){

                 

                  tipo_texto=texto2;

                 

                  estilo_letra=estilo2;

                 

                  tamano_letra=tam_letra;

                 

                  menu=elemento;

            }

Lo que vamos a hacer es instanciar la clase GestionaEventos, para ello nos vamos al método ConfiguraMenu antes de la llave de cierre:

submenus.addActionListener(new GestionaEventos(rotulo, tipo_letra, estilos, tam));

Y le pasamos como parámetros los parámetros del método.

Vamos al constructor de la lámina y en la llamada a la clase ConfiguraMenu hacemos lo siguiente para el tipo de letra:

ConfiguraMenu("Arial", "fuente", "Arial", 9,10);

           

            ConfiguraMenu("Courier", "fuente", "Courier", 9,10);

           

            ConfiguraMenu("Verdana", "fuente", "Verdana", 9,10);

Solo se va a encargar de cambiar el tipo de letra, los valores 9 y 10 son de ejemplo, no hacen nada. Para el estilo:

            ConfiguraMenu("Negrita", "estilo", "", Font.BOLD,1);

           

            ConfiguraMenu("Cursiva", "estilo", "", Font.ITALIC,1);

Para el tamaño:

            ConfiguraMenu("12", "tamano", "", 1,12);

           

            ConfiguraMenu("16", "tamano", "", 1,16);

           

            ConfiguraMenu("20", "tamano", "", 1,20);

           

            ConfiguraMenu("24", "tamano", "", 1,24);

Tenemos que detectar el submenú que pulsamos y que cambié el texto solo con la característica correspondiente del submenú, es decir, si pulsamos el tipo de texto Courier que solo modifique el tipo de texto, el estilo y el tamaño lo deje como esta.

Dentro del método actionPerformed tenemos que capturar el texto que escribimos para darle un tipo de texto, por ello ya nos creamos en su momento y una variable de clase llamada letras:

Font letras;

Capturamos el texto que hay en el área de texto:

public void actionPerformed(ActionEvent e) {

                 

                  letras=miarea.getFont();

                 

                  miarea.setFont(new Font(tipo_texto, estilo_letra, tamano_letra));

                 

            }

Con esto lo que conseguimos es almacenar en la variable letras el tipo de letra, el estilo y el tamaño seleccionado.

Para seleccionar cada uno de los elementos tenemos que utilizar varios métodos de la clase Font. Empezamos con el tipo de letra, mediante un condicional le vamos a indicar que si seleccionamos cualquier submenú Arial, Courier o Verdana el estilo y el tamaño nos los deje tal y como está:

public void actionPerformed(ActionEvent e) {

                 

                  letras=miarea.getFont();

                 

                  if(menu=="Arial" || menu=="Courier" || menu=="Verdana") {

                       

                        estilo_letra=letras.getStyle();

                       

                        tamano_letra=letras.getSize();

                  }

                 

                  miarea.setFont(new Font(tipo_texto, estilo_letra, tamano_letra));

                 

            }

Seguimos con el condicional para el estilo y el tamaño:

public void actionPerformed(ActionEvent e) {

                 

                  letras=miarea.getFont();

                 

                  if(menu=="Arial" || menu=="Courier" || menu=="Verdana") {

                       

                        estilo_letra=letras.getStyle();

                       

                        tamano_letra=letras.getSize();

                  }else if(menu=="Cursiva" || menu=="Negrita") {

                        if(letras.getStyle()==1 || letras.getStyle()==2) {

                             estilo_letra=3;

                        }

                        tipo_texto=letras.getFontName();

                       

                        tamano_letra=letras.getSize();

                  }else if(menu=="12" || menu=="16" || menu=="20" || menu=="24") {

                       

                        tipo_texto=letras.getFontName();

                       

                        estilo_letra=letras.getStyle();

                       

                  }

Con esto ya estaría terminado, probamos:



Si seleccionamos el tipo de letra 20:



Cambiamos el estilo a Cursiva comprobamos que el tamaño  y la fuente nos la mantiene igual:



Podemos mejorarlo si al seleccionar el tipo de letra nos muestre en consola el tipo de letra que hemos seleccionado:

miarea.setFont(new Font(tipo_texto, estilo_letra, tamano_letra));

                 

                  System.out.println("Tipo: "+tipo_texto+" Estilo: "+estilo_letra+" Tamaño: "+tamano_letra);

Si probamos cambiamos al fuente:



Con esto ya tendríamos terminado el procesador de textos, aun así es un procesador bastante básico tal y como lo tenemos solo permite cambiar las características de todo el texto, si seleccionamos parte del texto para que solo nos haga los cambios en el texto seleccionado no lo va a tener en cuenta, va a seguir modificando todo el texto que está en el área de texto. También el inconveniente que al seleccionar cursiva o negrita ya no le podemos quitar está característica al texto.

Para solucionar estos inconveniente se utiliza una clase StyledEditorKit() que permite seleccionar parte del texto y cambiar las característica solo del texto seleccionado y además permite quitar negrita y cursiva, es decir, si pulsamos negrita el texto se convierte en negrita si volvemos a pulsar negrita en el texto se elimina el estilo negrita.

Para utilizar esta clase tenemos que modificar el código, lo primero es que nos sobra la clase interna por lo que la eliminamos y también eliminamos la siguiente línea de código:

submenus.addActionListener(new GestionaEventos(rotulo, tipo_letra, estilos, tam));

Empezamos cambiando el tamaño del texto para ello nos metemos dentro del método y en el bloque condicional referente al tamaño escribimos lo siguiente:

else if(menu=="tamano") {

                 

                  tamano.add(submenus);

                 

                  submenus.addActionListener(new StyledEditorKit.FontSizeAction("cambia_tamaño", tam));

            }

Le pasamos dos parámetros, el segundo de ellos es el mismo parámetro que el método. Para los estilos:

else if(menu=="estilo") {

                 

                  estilo.add(submenus);

                 

                  if(estilos==Font.BOLD) {

                       

                        submenus.addActionListener(new StyledEditorKit.BoldAction());

                  }else if (estilos==Font.ITALIC) {

                       

                        submenus.addActionListener(new StyledEditorKit.ItalicAction());

                  }

Para el tipo de texto:

if(menu=="fuente") {

                 

                  fuente.add(submenus);

                 

                  if(tipo_letra=="Arial") {

                       

                        submenus.addActionListener(new StyledEditorKit.FontFamilyAction("cambia_letra", "Arial"));

                  }else if(tipo_letra=="Courier") {

                       

                        submenus.addActionListener(new StyledEditorKit.FontFamilyAction("cambia_letra", "Courier"));

                  }else if(tipo_letra=="Verdana") {

                       

                        submenus.addActionListener(new StyledEditorKit.FontFamilyAction("cambia_letra", "Verdana"));

                  }

Si probamos, seleccionamos texto y modificamos el tipo de letra y el tamaño, solo se modifica el texto seleccionado:



Con esto ya estaría terminado el procesador de textos, aquí os dejo el link con el código completo ya finalizado por si queréis modificarlo, añadir nuevas funcionalidades… Con cualquier duda me lo podéis hacer llegar a través de los comentarios del blog. Hasta pronto!

7.9 CREACIÓN DE MENÚS << >> 7.11MENÚ CON IMÁGENES



No hay comentarios:

Publicar un comentario