martes, 27 de junio de 2023

OOo Basic. Servicios

Trabajo con documentos: crear, abrir y cerrar

Lo primero que aprenderemos es a trabajar con documentos Presentación y Dibujo, esto es: a crear, abrir, guardar y cerrar uno de estos documentos mediante OOo Basic. Son aprendizajes comunes a cualquier otro servicio y algunos de ellos no presentan gran interés desde el punto de vista del uso que vamos a hacer de ellos, pero no nos vendrá mal su aprendizaje en el futuro; alguna utilidad le podremos dar.



Aprender a crear una presentación o un dibujo directamente, mediante OOo Basic no nos reporta una utilidad inmediata ya que no son archivos de los que vayamos a hacer un uso que pueda hacer útil este aprendizaje, pero conviene saberlo por lo que este código comparte con el uso de otros servicios.

Mauricio Baeza nos proporciona las claves para generar estos script que asociaremos a un archivo Writer desde el supuesto del uso de una presentación y/o una imagen como documento auxiliar en un proceso instruccional o de evaluación que se ilustra o soporta sobre este tipo de documentación auxiliar. Es por ello mismo que aprender a crear documentos de esta naturaleza carece de utilidad, pero nos dará una pista para otro tipo de usos, como veremos a continuación.

Sub Crear_Presenta

Dim sRuta As String
Dim mArg()
Dim oNuevaPresentacion As Object

sRuta = "private:factory/simpress"
        oNuevaPresentacion = StarDesktop.loadComponentFromURL( sRuta, "_default", 0, mArg() )

End Sub
 
Este script puede considerarse modelo de script para la creación de cualquier otro tipo de documento, por lo que me ahorro exponer el correspondiente para Draw. De hecho es suficiente con cambiar el servicio que se solicita desde la variable sRuta para generar el documento correspondiente:
  • scalc para hojas de cálculo.
  • swriter para documentos de texto.
  • simpress para presentaciones.
  • sdraw para dibujos.
  • smath para documentos Math.
El único servicio con el que no funciona es con Base, ya que crear una base de datos requiere procedimientos más complejos.

Ya dije que estos documentos vacíos nos sirven de bien poco, pero crear un documento de texto o una hoja de cálculo puede sernos de gran utilidad, así que bien está saber cómo crearlos.

Veamos ahora cómo acceder a un documento (presentación o dibujo ya creado), ya que este conocimiento sí puede sernos de gran utilidad en el planteamiento que realizamos antes: el dibujo o la presentación son, dentro de un docap complejo, recursos que utilizamos para presentar una información al usuario.

Sigo usando el documento de texto como base, pero ahora necesito que nuestros materiales gráficos ya estén creados de antemano y, para mayor comodidad, los supongo ubicados en la unidad D:

Sub Abrir_Presenta

Dim sRuta As String
Dim mArg()
Dim oPresenta As Object

sRuta = ConvertToUrl( "D:/PresentaPrueba.odp" )
oPresenta = StarDesktop.loadComponentFromURL( sRuta, "_blank", 0, mArg() )

 End Sub 

Mediante este script accedo al archivo presentación (extensión .odp) ubicado en el directorio raíz de la unidad D llamado PresentaPrueba. Podrá suponer que puedo seguir el mismo procedimiento para acceder a un archivo imagen, Calc o documento: es suficiente con cambiar el nombre (y al extensión) del archivo.

Esto quiere decir que también en este caso estamos hablando de un procedimiento generalizable, que podremos utilizar con cualquier documento que sea accesible a Libre Office, como por ejemplo, un .pdf, aunque en este caso se abre para ser gestionado por Draw, ya que  Libre Office lo interpreta como archivo de imagen. Igual sucede si lo intentamos con un archivo .txt : en este caso es abierto desde el servicio Writer, ya que Libe Office lo interpreta y asocia a un documento de texto.

De todas formas, lo importante de este script es entender la función que asociamos a la variable sRuta: la función ConvertToUrl(), que es la encargada de convertir a dirección absoluta, la dirección que introduzcamos entre sus paréntesis, siendo esta conversión necesaria para el funcionamiento del script por la naturaleza multiplataforma de Libre Office.

El script anterior podemos hacerlo interactivo introduciendo una variable o una serie de variables que nos permitan dar al programa la información necesaria. Este podría ser un ejemplo, aunque un tanto simple.

Sub Abrir_Interactivo

Dim sRuta As String, sUnidad As String, sNombreArchivo As String,

Dim sTipoArchivo As String, sExtension As String, sDireccion As String

Dim mArg()
Dim oDocInteractivo As Object
sUnidad = InputBox ("Unidad donde se encuentra el archivo")
sNombreArchivo = InputBox ("Nombre del archivo")
sTipoArchivo = InputBox ("Tipo de documento:")
If sTipoArchivo = "Impress" Then
sExtension = ".odp"
ElseIf sTipoArchivo = "Draw" Then
sExtension = ".odg"
End If
sDireccion = sUnidad & ":/" & sNombreArchivo & sExtension

sRuta = ConvertToUrl( sDireccion )
oDocInteractivo = StarDesktop.loadComponentFromURL( sRuta, "_blank", 0, mArg() )

End Sub

Esta funcionalidad no es de mucho interés para el planteamiento de docap que tenemos en mente, pero podría serlo para otros. 

Lo que también podemos derivar del análisis de los script anteriores es la posibilidad de crear una función o una subrutina que agilice el procedimiento, algo que resulta de utilidad para mejorar la formalización del código y que redunda en su funcionalidad si debemos reutilizar dicha función.

Function AbrirCualquierDoc(cRuta As String,Optional aOpciones()) As Object

cRuta = ConvertToURL(cRuta)
If IsMissing (aOpciones) Then aOpciones = Array()
        AbrirCualquierDoc = StarDesktop.LoadComponentFromURL(cRuta,"_blank",0, aOpciones())

End Function

Sub AbrirDocPresenta

Dim sDocum As String
sDocum = "D:/PresentaPrueba.odp"
AbrirCualquierDoc(sDocum)
End Sub

Gracias a esta función, es suficiente con dar el contenido requerido a la variable sDocum para que podamos acceder a cualquier tipo de archivo, con las condiciones y las opciones de interactividad que vimos antes.

Esta forma de trabajar nos permite dar un paso más en el acceso a documentos que presenten características específicas, lo que nos será de mucha utilidad. Dos ejemplos de ello, que no los únicos, son los siguientes:
  • Cuando el archivo (una presentación, por ejemplo) contiene macros
  • Y cuando queremos que la presentación se lance directamente.
Para ello daremos contenido al parámetro aOpciones declarado como opcional en la definición de la función y que ahora incluiremos en el script desde el que llamamos a la función.

Sub AbrirPresentaConMacros

Dim sDocum As String
Dim aOpc(0) As New "com.sun.star.beans.PropertyValue"
sDocum = "D:/PresentaPruebaSegunda.odp"
aOpc(0).Name = "MacroExecutionMode"
aOpc(0).Value = 4
AbrirCualquierDoc(sDocum,aOpc)
End Sub

Este script nos permite acceder a la presentación indicada en sDocum y activar sus macros directamente. Esto es posible por el uso de la variable aOpc que llama al método "com.sun.star.beans.PropertyValue", el cual, a su vez está conformado por una matriz de componentes Nombre-Valor que pueden ser usados simultáneamente siempre que no entren en contradicción entre sí.

Un ejemplo de uso simultáneo es el de abrir una presentación con macros y lanzarla directamente. El script que sigue al que acabo de exponer cumple ambos requisitos. Puedes acceder a él desde el documento que te dejo en uno de los enlaces al final de esta entrada.

Fíjate en que este caso, la función cumple la condición de SÍ presentar el argumento opcional aOpciones. Al haber sido definido de este modo y ser tratado mediante el condicional If, esta función nos sirve tanto para trabajar con script que no especifican propiedades específicas del documento como los que sí.

Para finalizar esta entrada, vamos a crear un script un tanto absurdo, pero que responde a una necesidad muy real: cerrar un documento previamente abierto. Lo absurdo deriva del modo de implementar estas funciones (guardar y cerrar), pero no de las funciones en sí, que pueden ser empleadas de forma mucho más lógica y funcional.

Sub AbrirCerrarDocum

Dim sRuta As String
Dim mOpciones(0) As New "com.sun.star.beans.PropertyValue"
Dim oDoc As Object

sRuta = ConvertToUrl( "D:/PresentaPrueba.odp" )
oDoc = StarDesktop.loadComponentFromURL( sRuta, "_blank", 0, mOpciones() )

'AQUI va todo el código que necesitemos para modificar el archivo abierto

MsgBox "Archivo abierto y modificado correctamente, presione Aceptar para guardar y cerrar"

'Guardamos los cambios
oDoc.store()

'Cerramos el archivo
oDoc.close(True)

End Sub

Las instrucciones claves (funciones, en realidad) son store(), que guarda los cambios realizados en el documento abierto) y close(), que lo cierra.

Si las utilizamos como se plantea en este script carecen de funcionalidad, ya que no nos es posible realizar cambio alguno en el archivo abierto (y ello por varios motivos, pero no vienen a cuento ahora), pero si las incorporamos a un script del documento (la presentación abierta desde el script "principal") podremos trabajar con la presentación (por ejemplo) y cerrarla guardando los cambios que deriven de su uso. 

Pero esto queda para futuros script. Por ahora ya tenemos más que suficiente, así que, para finalizar de dejo acceso a los documentos creados para ilustrar las funcionalidades trabajadas en esta entrada. La mayoría son únicamente necesarios en función de esta utilidad, pero el principal contiene en su IDE todos los script que hemos ido viendo a lo largo de esta entrada.
Recuerda que debes descargarlos en tu ordenador y ubicarlos en el directorio raíz de la una unidad D

OOo Basic. Servicios

 Uso de OOo Basic con Draw e Impress

En lo que se refiere al empleo de OOo Basic, Draw e Impress comparte una limitación: ninguno de los dos permite grabar macros, aunque el resto de las funcionalidad relacionadas con OOo Basic sí están disponibles. En consecuencia, y en sentido estricto, no Impress ni Draw permiten la creación y ejecución de macros, pero sí de script OOo Basic.


Esta imposibilidad para grabar macros está justificada por el modo de trabajo que conllevan ambos servicios, pero no deja de plantear limitaciones para la creación de secuencias de código: no podemos disponer de la ayuda que proporciona la función Grabar macros en Calc y en Writer para superar las limitaciones que podemos tener para crear funcionalidades. En Impress y en Draw dependemos totalmente de nuestro conocimiento del lenguaje OOo Basic, y este es, hoy por hoy, limitado.

En cierto modo, esta limitación de ambos servicios también conlleva limitaciones que afectan al modo de uso de los script y de su interacción con el servicio, aunque en esto las posibilidades de asociar cada forma gráfica con un script en Impress o de incluir elementos de un formulario en Draw (aquí son de especial interés los botones de comando) permiten acceder a la implementación de script también con los gráficos estáticos o dinámicos y los MAV que podemos crear con ambos.

Las utilidades que derivan de estas posibilidades nos permiten idear usos de los soportes gráficos más allá de la simple ilustración/instrucción. Estas posibilidades se incrementan si pensamos en el uso combinado de  Draw y/o Impress con Calc y/o con Writer, ya que de este modo podemos diseñar docap que aprovechen el potencial de estos servicios, incrementado con el que genera la utilización de OOo Basic.

Pero antes de llegar a estas metas, es necesario recorrer un camino que iniciaremos en la próxima entrada de esta serie. En ella y en las que la sigan mostraré cómo crear script que nos permitan trabajar con documentos (archivos Draw y presentaciones Impress) y con algunos de sus componentes. Posteriormente trabajaremos sobre la implementación de script que resulten funcionales desde una imagen y/o desde un objeto de una presentación.

Este es en resumen el camino que te propongo seguir en las entradas del menú GRÁFICOS.

lunes, 26 de junio de 2023

Gráficos. Introducción.

 Introducción a Draw e Impress

Tanto Impress como Draw nos permiten trabajar con imágenes estáticas (Draw) o dinámicas (Impress), así como con el uso combinado de medios multimedia (fundamentalmente Impress). Además Impress es a Libre Office lo que Power Point es a Microsoft Office.


Las posibilidades que ofrecen Impress y Draw de trabajar con imágenes nos permiten pensar en el desarrollo de recursos orientados al desarrollo de recursos educativos, pero también de materiales para la evaluación. En su ámbito específico, ambos ofrecen posibilidades que, aunque también estén presentes en Calc y en Writer, lo están de forma limitada.

El uso de Draw, pero sobre todo de Impress, como servicios para crear documentos multimedia cae dentro del dominio standard de ambas herramientas, motivo por el cual al final de esta entrada ofrezco dos enlaces a manuales de uso.

Pero ambos también permiten el uso de script basados en OOo Basic, aunque éste y las posibilidades que conlleva, presenta características que podemos considerar limitaciones en comparación con las posibilidades que ofrece el uso de OOo Basic en Calc y en Writer.

Aun así he considerado interesante compartir el uso de OOo Basic en ambos soportes y proponer algunas estrategias de trabajo con ellas. Esto añade valor a lo que OOo Basic aporta al uso de Calc y de Writer e ilustra algunas posibilidades de trabajo con Impress y con Draw que complementan las que derivan del uso ordinario de ambos servicios.    

Las entradas contenidas y asociadas a este identificador y subíndice (Gráficos) irán dirigidas a estos fines. Los documentos a los que puedes acceder desde los enlaces que siguen a continuación te pueden servir para que desarrolles un conocimiento avanzado el uso standard de estas herramientas. Con ambos (manuales de uso y entradas) pretende poner a tu disposición conocimientos suficientes para que saques el máximo partido de Draw y de Impress como recursos para la creación de docap.

Documentos

martes, 20 de junio de 2023

OOo Basic. Datos

 Variables lógicas, de objeto y de tipo variable

Para finalizar la revisión del tipo de variables de OOo Basic, trataremos en esta entrada sobre las variables lógicas (Boolean), de tipo variable (Variant) y de tipo objeto (Object)




Las variables lógicas se conocen en OOo Basic como Boolean y son aquellas que pueden tener únicamente dos valores: True o False, y sus equivalentes "numéricos" (1 - 0). Permiten representar datos con dos opciones de presentación (0-1), como es el caso de la respuesta a preguntas del tipo...

¿Llegaste a la meta? -> Admite dos posibles respuestas: Sí (True) 1 vs. No (False) 0

¿Es niño? -> Admite dos posibles respuestas: Sí (1) -> Es niño vs. No (0) -> Es niña. 

Además de las variables declaradas como booleanas, este tipo de análisis también puede ser realizada sobre cualquier variable o expresión en contextos de condicionalidad, ya que en ellos lo que se hace es juzgar en términos V|F el cumplimiento de una condición. Por ejemplo:

Dim sDato  As String, sTipo As String

sDato = "Perro"

If sDato = "Perro" Then

sTipo = "Animal"

End If 

En este caso la variable sDato es de tipo string, pero cuando se emplea dentro del condicional If lo que analizamos es el cumplimiento de una equivalencia (no la asignación precedente sDato = "Perro"), así que si se cumple que sDato = "Perro" (esto es, si sDato = "Perro" es True, como es el caso), entonces se realiza la asignación (ahora sí, asignación) sTipo = "Animal". De no cumplirse la condición anterior, no se efectúa dicha (segunda) asignación. (1)

Otra situación en la que es interesante el uso de variables Boolean es cuando como resultado de una categorización, una variable puede tener asignados contenidos identificables dentro de dicha categoría, resultando, no obstante, suficientemente complejo el análisis de los mismos cuando nos interesa algún tipo de análisis de la tabla o base de datos resultante.

En este caso una opción frecuente es generar tantas variables como elementos tenga la categoría (al menos tantas como se presenten en los datos obtenidos), las cuales se identifican o denominan como la categoría, y que se definen como variables booleanas. Esto facilita su análisis posterior. Un ejemplo:

  • Dim sCatNE As String requiere como respuesta tres categoría "ORD", "NEAE", "NEE".
  • Podemos "desglosarla en tres variables Boolean (Dim vORD As Boolean, vNEAE As Boolean y vNEE As Boolean) a las que se responde como True o False. Esta diferenciación no tiene mucho interés cuando se trabaja con casos individuales, pero facilita los análisis posteriores de la base de datos que resulte de su aplicación a un colectivo.

Para la valoración de las expresiones booleanas contamos con las llamadas [tablas de verdad]

Las variables Variant permiten a OOo Basic tratar variables cuyo contenido no está definido a priori y es, por tanto, variable. Viene a ser el equivalente a no delimitar expresamente el (tipo de) contenido o dato de una variable. Variant da flexibilidad al lenguaje a costa de un consumo mayor de memoria RAM, por lo que su uso debe quedar restringido a lo necesario. Un ejemplo de uso del tipo Variant se da en la definición de las matrices por razones que se comentarán en su momento.

Finalmente las variables tipo objeto (Object) permiten almacenar en un variable cualquier objeto definido en la API de LibreOffice. Dado que LibreOffice es una suite construida en gran medida sobre Java, que es un lenguaje orientado a objetos (POO), el uso de variables de tipo objeto es muy frecuente en los script OOo Basic, permitiendo a este lenguaje acceder a los componentes fundamentales de la suite LibreOffice y sus diferentes servicios.

Un ejemplo de variable tipo Object es la que permite a OOo Basic acceder al documento sobre el que se construye el script:

Dim oDoc As Object, oHojaActiva As Object

oDoc = ThisComponent
oHojaActiva = oDoc.getCurrentController.getActiveSheet()

En este caso estamos construyendo el script sobre la hoja activa del documento Calc. Al documento se accede mediante la variable objeto oDoc (a la que se asocia el propio documento mediante el identificador ThisComponent). 

A la hoja activa se accede mediante la variable oHojaActiva que se asocia a oDoc.getCurrentController.getActiveSheet().

NOTA

(1) En este caso estamos hablando de operadores relacionales más que de variables. La coincidencia entre el operador relacional de igualdad o equivalencia (=) y el operador de asignación (también =) da lugar a confusiones. Sobre este tema [ver aquí]. Otros lenguajes, como Python, diferencian entre el operador de asignación y el de equivalencia, lo que evita este tipo de confusiones.

lunes, 19 de junio de 2023

OOo Basic. Datos

Variables numéricas (1)

Existen en OOo Basic cinco tipos de variables numéricas, tres de tipo entero y dos de tipo decimal o de coma flotante. Las variables numéricas son las segundas en importancia de uso en los script útiles para la intervención de los SEO, tanto para los cálculos internos del script como para el manejo de la información documental. Un ejemplo claro es un docap sobre pruebas de evaluación; otro podría ser (aunque no lo es con la suficiente frecuencia) el análisis de las propias actuaciones. En ambos contextos, el manejo de datos numéricos son fundamentales.




Podría parecer que tanto tipo de variables numéricas fuera innecesario, y en la práctica suele ser suficiente con un par de ellas (una de tipo entero y  otra de tipo decimal), pero para usos amplios del lenguaje sí es necesario, ya que mejora el uso de la memoria RAM del ordenador. veamos cuáles son esos tipos de variables.

Para ello nada mejor que esta tabla extraída del manual de Mauricio Baeza que nos ayudará a identificar con rapidez el nombre, el tipo y los datos que contiene cada una de esas variable.

Posiblemente te habrás dado cuenta que los tipos mas usados van a ser dos: Integer y Single, uno de cada tipo (entero y decimal). El tipo Byte (entero) podría ser más que suficiente para la mayoría de nuestros script, pero tiene un límite superior muy bajo, por lo que se puede ver desbordado con facilidad. Single tiene el "problema" de ser menos conocido que Double, por lo que es más frecuente usar el tipo más amplio con el consecuente desperdicio de memoria, por eso he optado por privilegiarlo.

No obstante, según los números que se manejes y las operaciones que se realicen con ellos, debemos contar con todos los tipos numéricos disponibles, ya que nuestra primera elección puede resultar inapropiada como resultado de la operatoria. Ese es el caso de Integer frente a Long y de Single frente a Double, pero no sólo, ya que no es infrecuente que de la operatoria entre dos valores Integer surja como resultado un valor decimal (Single o Double).

Finalmente Currency es un tipo derivado o de segundo nivel y tiene características muy específicas por su naturaleza, siendo su uso muy recomendable para el tratamiento de valores monetarios en contextos específicos de contabilidad o gestión económica. Al margen de estas situaciones, su uso es más bien irrelevante, como en nuestro contexto profesional.

La forma de trabajar con estas variables es la misma que con las variables alfanuméricas:

  • Declaramos y tipificamos: Dim Num as Integer
  • Y asignamos contenido, bien directamente [num= 24], bien como resultados del procesamiento de otras variables o datos [num= 20 + 5 , num = num1 + num2]. En este segundo caso ya entramos en la fase Procesamiento. (2)

Ahí es donde entran en juego los operadores aritméticos, que son los signos que empleamos para representar las operaciones aritméticas. No son los únicos que podemos utilizar con las variables numéricas (veremos otros en otras entradas), pero sí los más frecuentes. El manual de Mauricio Baeza simplifica nuestra exposición (3).


Es de interés explicar más detalladamente tres operadores relacionados con la división, por la importancia de su uso en la práctica. Me refiero a los operadores / (división con posible cociente decimal) frente a la división entera (\), donde el resultado (cociente) siempre será un número entero (la operación se "detiene" una vez obtenida la parte entera, quedando el resto como tal). La información sobre esta última división (\) se complementa con el operador Mod, que devuelve el resto de esa división (que devuelve el resto, esto es: "lo que queda sin repartir"). 

Diferentes script plantean algunas de las cuestiones que pueden ser de interés:
  • Errores por encadenamiento vs. suma, como el que se muestra en el script Operaciones1, cuando "sumamos" un valor numérico con otro alfanumérico...

Sub Operaciones1

Dim NumA As string
Dim NumB As Byte, NumR As Byte

NumA = "25"
NumB = 2

NumR = NumA + NumB             -> Resultados 252, encadena 25 y 2

NumR = CInt(NumA) + NumB    -> Resultado 27, suma 25+2


End sub

... obteniendo como resultado la concatenación de ambos. Para evitarlo es necesario convertir previamente el valor alfanumérico en numérico mediante CInt()

  • Errores por truncamiento, que se producen cuando, necesitando precisión, utilizamos variables enteras y obtenemos un resultado que trunca la parte decimal. El resultado es correcto en función de las variables utilizadas, pero no desde la perspectiva de la operación, lo que puede dar lugar a errores de apreciación.
  • También se pueden dar errores por desbordamiento, que son resultado de una operación que desborda las dimensiones del tipo de variable al que se asigna. Un ejemplo lo podemos ver en el script Operaciones3

Sub Operaciones3

Dim Num1 As Integer
Dim NumR As Long

Num1 = 234

NumR = Num1 ^ 2

End Sub

... que provoca error por desbordamiento en NumR; error que desaparece si transformamos esta variable al tipo Long.

El documento para trabajar con estos script [está aquí a tu disposición]. 

NOTAS

(1) Entrada publicada el 19/06/2023 revisada el 2/05/2024. Las modificaciones son mínimas, por lo que se mantiene la fecha de la publicación original.

(2) Observa que, al contrario que los datos alfanuméricos, los numéricos no se escriben entrecomillados. Precisamente la diferencia tipológica entre "24" como cadena alfanumérica y 24 como número se identifica por el uso/no uso de las comillas.

(3) No son estos los únicos operadores aritméticos, como podemos ver en [Walter Mora; F] (pp. 24-24), pero sí los de uso más frecuente. En Mora se recogen mezclados operadores y funciones con función de operadores, y no sólo de tipo aritmético, por lo que resulta un tanto confuso para nuestra exposición.

Python. Interface.

 TKinter. Selección de opción (ComboBox)

Próximo a la entrada (Entry) en cuanto a objetivo y función, el Combobox es un componente que permite al usuario elegir uno de los elementos de la lista de opciones del widget.


En esta entrada veremos el modo básico de implementarlo en un formulario tKinter siguiendo los dos procedimientos básicos: configuración y posicionamiento, aunque este último sólo con un objetivo funcional, que no didáctico.

Esta es la apariencia del formulario resultante del script que sirve de base, pobre de solemnidad, pero suficiente para que nos entendamos...


Observa el parecido con un Entry, siendo de hecho, la única diferencia observable (y después comprobable también en cuanto funcionamiento) la presencia de una pequeña flecha orientada hacia abajo y posicionada en el extremo derecho de la caja. 

Como seguramente ya sabes, haciendo clic en esta flechita se despliega una lista de opciones de las cuales el usuario selecciona una, no pudiendo introducir otros contenidos que los disponibles en esta lista. Este es el funcionamiento esperable que se logra del siguiente modo:

combo = ttk.Combobox(
    state="readonly",
    values=["Python", "C", "C++", "Java"])
combo.place(x=50, y=50)

NOTA. Nos olvidarnos de la última línea ya que, como sabemos, constituye el procedimiento para posicionar el componente.
  • Primero asociamos el componente con el tipo de objeto perteneciente a tKinter
combo = ttk.Combobox()

  • Después, ya dentro del paréntesis, establecemos que no es posible al usuario introducir datos propios, indicando que este componente es sólo de lectura:

 state="readonly",

NOTAEste es el comportamiento esperado, pero si queremos que el usuario puede incluir opciones no previstas, podemos eliminar este atributo. 

  • Finalmente establecemos la lista de opciones utilizando para ello una lista asociada al atributo valores (values)
values=["Python", "C", "C++", "Java"])

NOTAObserva el uso de corchetes para delimitar la lista y de comas y comillas para delimitar cada elemento. La similitud de Combobox con Entry se concreta en este caso, con que los valores de la lista son siempre asimilados a texto (de ahí que vayan entrecomillados), por lo que así será tratado cualquier valor aparentemente numérico que utilicemos.

Nos falta aprender muchas cosas sobre el uso de combobox, especialmente cómo accedemos a su contenido, pero esto queda para una entrada posterior. Por ahora, si lo deseas, puedes jugar con el código de este script para aprender a crearlos. También te puede ser útil esta página para saber más sobre este widget 

domingo, 18 de junio de 2023

Python. Aplicaciones.

 Aplicaciones. Uso de variables y métodos

Avanzando en los conocimientos necesarios para crear aplicaciones viables utilizando tKinter, a los conocimientos necesarios sobre componentes y su posicionamientos, es necesario añadir el uso de variables de control y de los métodos para acceder al contenido de los componentes del formulario. Dedicaremos esta entrada a este fin.


Empezaré por las variables de control, que son objetos (no sólo variables en sentido estricto) que se asocian a los componentes o widgets para almacenar sus valores y facilitar que éstos estén disponibles para el programa. Al igual que las variables, pueden ser de diferente tipo y se declaran de forma específica, siendo posible atribuirles datos o contenido en el momento en que se declaran:
  • nEntero = IntVar(value=1) -> Objeto variable entero con valor 1
  • nDecimal= DoubleVar(value=12,5) -> Objeto variable double con valor 12,5
  • tFrase=StringVar(value="Nombre del alumno") ->Objeto variable string con valor "Nombre del alumno"
  • bDatos=BooleanVar(value=True) -> Objeto variable booleana con valor Verdad (True)
El uso de estos objetos se combina con el de los métodos get(), set() y trace() que tienen respectivamente las siguientes funciones:
  • get() permite obtener el valor que contenga una variable de control y se emplea cuando es necesario conocer ese valor o dato
print ("Valor de la variable nEntero: ", nEntero.get())

  • set() asigna un valor o datos a una variable de control y se utiliza para modificar el valor o estado de un componente o widget
sNombre = StringVar()
sNombre.set("Python para principaiantes")
eTexto= tk.Label(ventana,textvariable=sNombre) 

NOTAObserva que, en este caso, el parámetro que empleamos en la definición de la etiqueta sTexto no es text sino textvariable.

  • trace() se emplea para "detectar" cuando una variable es leída, cambia de valor o es borrada. 
Dado que, por el momento no vamos a trabajar con el método trace(), no seguiré explicando aquí su uso. Dedicaremos el resto de esta entrada a ejemplificar con cierto detalle el uso de los anteriores (get() y set()) desarrollando un script de ejemplo.

Python. Interface.

 TKinter. Botón de opción (Radiobutton)

Cuando interesa facilitar la elección de una opción predefinida como como excluyente y formando parte de un conjunto limitado de posibilidades, los botones de opción (en tKinter Radiobutton) son posiblemente el componente más adecuado.


Vamos a ver en esta entrada cómo se configura, en realidad configuran, ya que cada opción necesaria (cada botón de radio) se concreta como un componente.

Eliminando del script el código necesario para el posicionamiento, el que se precisa para configurar estos componentes (tres en este caso) es el siguiente:

clase1 = tk.Radiobutton(ventana,

                        text='Clase turista (t)',

                        variable=clase,

                        value='t')

clase2 = tk.Radiobutton(ventana,

                        text='Primera clase (p)',

                        variable=clase,

                        value='p')

clase3 = tk.Radiobutton(ventana,

                        text='Clase Vip (v)',

                        variable=clase,

                        value='v')

Observa que todos hacen referencia a la misma variable (clase) y que cuentan también con un atributo de valor (value='t', por ejemplo). Mientras que esa referencia a la variable da unidad al conjunto, el valor específico (y diferente para cada botón) permitirá el posterior tratamiento del resultado del uso del formulario.

Pero como en otras ocasiones, también aquí eso queda para una entrada posterior. De momento aquí tienes el script de uso de radiobutton para que lo analices. 

Python. Interface.

 TKinter. Checkbutton

También llamado checkbox es un componente de formulario que presenta dos opciones: activado vs. desactivado, lo que equivale a considerarlo como booleano. También puede presentar un estado intermedio no activado, que no equivale formalmente a desactivado, aunque sí funcionalmente.


Su uso en un formulario es similar al de los botones de opción, aunque se diferencia de éstos en que no va asociado a un grupo de opciones.

En la creación de un checkbutton, al igual que la del resto de componentes, se diferencian dos fases: configuración y posicionamiento. Dado que la segunda no aporta especificidad y ya la hemos visto en anteriores entrada, y teniendo en cuenta que le dedicamos una entrada específica, en ésta me limitaré a explicar cómo se desarrolla la fase de configuración.

En primer lugar, identificamos el componente con un nombre y la definimos como parte de tkinter y por su tipo:

  idavuelta = tk.Checkbutton()

NOTA. Obviamente, este checkbutton es inoperante aunque no lo aparente si esta primera formulación está acompañada de la de posicionamiento.

A continuación identificamos el contenedor al que va asociado, siguiendo (hasta el momento) el mismo procedimiento que para cualquier otro componente del formulario.

idavuelta = tk.Checkbutton(ventana)

Es a partir de este momento cuando empezamos a introducir atributos específicos del componente hasta finalizar su configuración...

idavuelta = tk.Checkbutton(ventana,

                        text='Ida y vuelta',

                        variable=ida_vue,

                        onvalue=True,

                        offvalue=False)

 ... aunque la más específica es la que otorga significado booleano a sus dos estados: onvalue y offvalue. Además es necesario asociar una variable al checkbutton para poder acceder al estado del componente, ya que su utilidad dentro de un formulario radica precisamente en eso, yendo generalmente asociado a formulaciones en términos de opcionalidad (if), pero esta es ya otra historia que contaremos cuando corresponda.

De momento nos quedamos con el script para poder manipularlo y valorar las consecuencias.