import threading import time import tkinter.ttk from tkinter import * from tkinter import messagebox from PIL import Image, ImageTk from _datetime import date import re from ImpetomC import ImpetomC from ImpetomCError import ImpetomCError from ImpetomCElectrodeError import ImpetomCElectrodeError from datetime import datetime import winsound """ Clase que genera la interfaz gráfica de la aplicación """ """ Variables globales de la aplicación """ arduinoImpetom = 0 # 0 indica arduinoImpetom desconectado, 1 indica que esta conectado Reconstruir = False mode = "Setup" img = Image.open('imagenInicial.jpg') sclRangeEnable = False """ Funciones para validación de datos de entrada """ def validateName(): """ Funcion que valida el nombre del paciente ingresado :return: 0 si existe algun error, 1 si el nombre es correcto (el campo lblNameError no esta vacio) """ ret=0 patName = txtName.get("1.0", END) if len(patName) <=1 : lblNameError.config(text="Este campo no puede estar vacío") else: ret=1 lblNameError.config(text="") return ret def validateCI(): """ Funcion que valida la CI del paciente ingresado :return: 0 si existe algun error, 1 si la CI es correcta (el campo lblNameError no esta vacio) """ ret = 0 patCi = txtCi.get("1.0", END).strip("\n") lenCI=len(patCi) if not re.match('^[0-9]*$',patCi): lblCiError.config(text="La CI solo puede contener números") elif lenCI <= 6 or lenCI > 8: lblCiError.config(text="CI inválida") else: ret = 1 lblCiError.config(text="") return ret def arduinoImpetomConected(): """ Funcion que verifica que el dispositivoImpetomC esta conectado :return: 0 si existe algun error, 1 si no """ ret = 1 global arduinoImpetom if arduinoImpetom == 0: try: # Verifico que haya un arduino conectado al equipo al iniciar y si es el arduino de ImpetomC ImpetomC.startUp() arduinoImpetom = 1 # indicador que arduino Impetom está conectado lblError.config(text="", bg='white') except ImpetomCError as e: lblError.config(text=str(e), bg='white') arduinoImpetom = 0 ret = 0 return ret def validateSexoBiologico(): """ Funcion que valida el sexp biologico del paciente ingresado :return: 0 si existe algun error, 1 si no """ ret = 0 patSex = cmbBioSex.get().lower() if patSex == "seleccionar": lblBioSexError.config(text="Seleccione una opción válida") else: lblBioSexError.config(text="") ret = 1 return ret def validateBirthDate(): """ Funcion que valida la fecha de nacimiento del paciente ingresado :return: 0 si existe algun error, 1 si no """ ret = 0 txtBDate = str(txtBirthDate.get("1.0", 'end-1c')) try: datetime.strptime(txtBDate, "%d-%m-%Y") lblBirthDateError.config(text="") ret = 1 except ValueError: lblBirthDateError.config(text="La fecha debe ser dd-mm-yyyy") finally: return ret def validateMedida(): """ Función que valida la entrada de los datos de medida de circunferencia del tórax, El dato debe ser un número entre 100 y 2000mm """ ret = 0 fantomaMed = txtMedida.get("1.0", END).strip("\n") lenFantomaMed = len(fantomaMed) if not re.match('^[0-9]*$', fantomaMed): lblMedidaError.config(text="Este campo solo puede contener números positivos") elif lenFantomaMed <= 2: # Verifico que el número sea mayor que 100 mm lblMedidaError.config(text="El perímetro debe ser mayor o igual a 100 mm") elif lenFantomaMed >= 5: lblMedidaError.config(text="El perímetro es demasiado grande") else: ret = 1 lblMedidaError.config(text="") if lenFantomaMed == 4: intFantomaMed = int(fantomaMed) if intFantomaMed >= 2000: lblMedidaError.config(text="El perímetro es demasiado grande") ret = 0 return ret def validateMedidaZ(): """ Función que valida la altura de colocación del cinturon, debe estar entre 10 mm y 999mm """ ret = 0 fantomaMedZ = txtMedidaZ.get("1.0", END).strip("\n") fantomaMedZ = fantomaMedZ.strip("-") # Para validar ints > 0 y < 0 con la misma regExp lenFantomaMedZ = len(fantomaMedZ) lblMedidaZError.place(x=(265 / 1200) * screenWidth, y=(560 / 750) * screenHeight) if not re.match('^[0-9]*$', fantomaMedZ): lblMedidaZError.config( text="La altura de colocación del cinturón debe ser un número entero medido desde la apófisis del esternón") elif lenFantomaMedZ < 1 or lenFantomaMedZ > 3: # lblMedidaZError.config(text="La referencia de altura no es válida") else: ret = 1 lblMedidaZError.config(text="") return ret """ Eventos para botones Start y Stop """ def btnStartClicked(): """ Evento del botón start """ global Reconstruir, arduinoImpetom if validateName() +validateCI() + arduinoImpetomConected() + validateSexoBiologico() + validateBirthDate() + validateMedida() + validateMedidaZ() == 7: Reconstruir = True txtMedida.config(state='disable') txtMedidaZ.config(state='disable') txtName.config(state='disable') txtCi.config(state='disable') btnIncTime.config(state='disable') btnIncTime2.config(state='disable') btnDecTime.config(state='disable') btnDecTime2.config(state='disable') btnStart.config(state='disable') lblTimeError.config(text="Presione Stop para cambiar esta opción") btnReconstruccion.config(state='disable') btnSetup.config(state='disable') cmbModel.config(state='disable') lblModeMessage.config(text='Presione Stop para cambiar esta opción') btnCalibrar.config(state='disable') btnReset.config(state='disable') threading.Thread(target=reloadImage).start() def btnStopClicked(): """ Evento del botón Stop """ global Reconstruir Reconstruir = False time.sleep(4) txtMedida.config(state='normal') txtMedidaZ.config(state='normal') txtName.config(state='normal') txtCi.config(state='normal') btnIncTime.config(state='normal') btnIncTime2.config(state='normal') btnDecTime.config(state='normal') btnDecTime2.config(state='normal') btnStart.config(state='normal') btnStop.config(state='disable') lblTimeError.config(text="") lblModeMessage.config(text='') btnCalibrar.config(state='normal') btnReset.config(state='normal') if mode == "Setup": btnReconstruccion.config(state='normal') else: btnSetup.config(state='normal') cmbModel.config(state='readonly') def btnResetClicked(): """ Evento para el botón reset """ global img, photo lblDate.config(text="Fecha: " + str(date.today().strftime("%b-%d-%Y"))) btnReset.config(state='disable') ImpetomC.reset() img = Image.open('imagenInicial.jpg') photo = ImageTk.PhotoImage(img) lblImg.config(text="", image=photo, width=(700 / 1200) * screenWidth, height=(500 / 750) * screenHeight) cmbModel.current(0) lblpRangeValue.config(text=initialPValue) lblGananciaValue.config(text=initialGValue) lblVmaxValue.config(text=initialVmaxValue) lblVminValue.config(text=initialVminValue) lblSaveTimeValue.config(text=initialSaveTimeValue) lblError.config(text="", bg="white") btnSetupClicked() rbtnSclOptionsDisable.select() if tkinter.messagebox.askyesno("Reset", "Desea también eliminar los datos del paciente?"): txtName.delete("1.0", "end") txtCi.delete("1.0", "end") txtMedida.delete("1.0", "end") txtMedidaZ.delete("1.0", "end") txtBirthDate.delete("1.0", "end") cmbBioSex.current(0) """ Esta función se encarga de actualizar las imágenes en lblImg """ def reloadImage(): """ Esta funcion es la encargada de actualizar las imagenes en la etiqueta lblImg """ global img, photo, arduinoImpetom, Reconstruir, bpWeight, screenWidth, sclRangeEnable, mode ti = time.time() while Reconstruir: try: medida = txtMedida.get("1.0", END).strip("\n") medidaZ = txtMedidaZ.get("1.0", END).strip("\n") vmax = float(lblVmaxValue.cget("text")) vmin = float(lblVminValue.cget("text")) pvalue = round(float(lblpRangeValue.cget("text")), 2) frecValue = str(30000 - int(lblGananciaValue.cget("text")) * 100) shape = cmbModel.get().lower() pacBDate = str(datetime.strptime(txtBirthDate.get("1.0", 'end-1c'), "%d-%m-%Y").strftime("%Y%m%d")) pacSex = cmbBioSex.get() ImpetomC.generarImagenTomografica(vmax=vmax, screenWidth=screenWidth, sclEnable=sclRangeEnable, vmin=vmin, mode=mode, shape=shape, p=pvalue, frecuenciaDDS=frecValue) tf = time.time() elapsedTime = int(tf - ti) img = Image.open('IMG.jpg') photo = ImageTk.PhotoImage(img) lblImg.config(text="", image=photo) lblError.config(text="", bg='#2b70e4') if elapsedTime > int(float(lblSaveTimeValue.cget('text')) * 60): # Conversión de minutos a segundos ImpetomC.guardarImagenEnHistoriaClinica(pacientName=txtName.get("1.0", END), pacientCi=txtCi.get("1.0", END), p=pvalue, pacSex=pacSex, pacBirthDate=pacBDate, medida=medida, shape=shape, medidaZ=medidaZ, mode=mode) ti = time.time() if Reconstruir: btnStop.config(state='normal') except ImpetomCError as e: # errores por problemas de conexion del dispositivo Arduino lblError.config(text=str(e) + " Por favor verifique la conexión y presione start nuevamente", bg='white') winsound.Beep(440, 500) Reconstruir = False arduinoImpetom = 0 # arduino ImpetomC no está conectado btnStopClicked() ImpetomC.guardarImagenEnHistoriaClinica(pacientName=txtName.get("1.0", END), pacientCi=txtCi.get("1.0", END), p=pvalue, pacSex=pacSex, pacBirthDate=pacBDate, medida=medida, shape=shape, medidaZ=medidaZ, mode=mode) except ImpetomCElectrodeError as e: # Errores detectados sobre los electrodos lblError.config(text=str(e), bg='white', fg='#f00') tf = time.time() elapsedTime = int(tf - ti) img = Image.open('IMG.jpg') photo = ImageTk.PhotoImage(img) lblImg.config(text="", image=photo) if e.regularGanancia and elapsedTime > int(float(lblSaveTimeValue.cget( 'text')) * 60): # Para errores de regular ganancia se guarda la imágen, si son errores de falso contacto no se guarda la imágen ImpetomC.guardarImagenEnHistoriaClinica(pacientName=txtName.get("1.0", END), pacientCi=txtCi.get("1.0", END), p=pvalue, pacSex=pacSex, pacBirthDate=pacBDate, medida=medida, shape=shape, medidaZ=medidaZ, mode=mode) ti = time.time() elif not e.regularGanancia: winsound.Beep(440, 500) if Reconstruir: btnStop.config(state='normal') except RuntimeError: # Se esta recontruyendo la imagen y se presiona el botón de salir time.sleep(5) root.destroy() """ Funciones botones p del jac """ maxPValue = 0.9 minPValue = 0.05 def incPRange(): """ Evento del boton ">" de p """ enableDecpRange() pRangeValue = float(lblpRangeValue.cget("text")) pRangeValue += 0.01 if pRangeValue >= maxPValue: pRangeValue = maxPValue disbleIncpRange() lblpRangeValue.config(text=str(round(pRangeValue,2))) def incPRange2(): """ Evento del boton ">>" de p """ enableDecpRange() pRangeValue = float(lblpRangeValue.cget("text")) pRangeValue += 0.1 if pRangeValue >= maxPValue: pRangeValue = maxPValue disbleIncpRange() lblpRangeValue.config(text=str(round(pRangeValue,2))) def decPRange(): """ Evento del boton "<" de p """ enableIncpRange() pRangeValue = float(lblpRangeValue.cget("text")) pRangeValue -= 0.01 if pRangeValue <= minPValue: pRangeValue = minPValue disableDecpRange() lblpRangeValue.config(text=str(round(pRangeValue,2))) def decPRange2(): """ Evento del boton "<<" de p """ enableIncpRange() pRangeValue = float(lblpRangeValue.cget("text")) pRangeValue -= 0.1 if pRangeValue <= minPValue: pRangeValue = minPValue disableDecpRange() lblpRangeValue.config(text=str(round(pRangeValue,2))) def enableIncpRange(): """ Permite habilitar los botones ">>" y ">" de p """ btnIncpRange.config(state="normal") btnIncpRange2.config(state="normal") def enableDecpRange(): """ Permite habilitar los botones "<" y "<<" de p """ btnDecpRange.config(state="normal") btnDecpRange2.config(state="normal") def disbleIncpRange(): """ Permite deshabilitar los botones ">>" y ">" de p """ btnIncpRange.config(state="disable") btnIncpRange2.config(state="disable") def disableDecpRange(): """ Permite deshabilitar los botones "<" y "<<" de p """ btnDecpRange.config(state="disable") btnDecpRange2.config(state="disable") """ Eventos de los botones para el manejo de la ganancia """ maxGananciaValue = 5 minGananciaValue = -20 def incGanancia(): """ Evento del boton ">" de la ganancia del sistema """ enableDecGanancia() gananciaValue = int(lblGananciaValue.cget("text")) gananciaValue += 1 if gananciaValue >= maxGananciaValue: gananciaValue = maxGananciaValue disableIncGanancia() lblGananciaValue.config(text=gananciaValue) def incGanancia2(): """ Evento del boton ">>" de la ganancia del sistema """ enableDecGanancia() gananciaValue = int(lblGananciaValue.cget("text")) gananciaValue += 5 if gananciaValue >= maxGananciaValue: gananciaValue = maxGananciaValue disableIncGanancia() lblGananciaValue.config(text=gananciaValue) def decGanancia(): """ Evento del boton "<" de la ganancia del sistema """ enableIncGanancia() gananciaValue = int(lblGananciaValue.cget("text")) gananciaValue -= 1 if gananciaValue <= minGananciaValue: gananciaValue =minGananciaValue disableDecGanancia() lblGananciaValue.config(text=gananciaValue) def decGanancia2(): """ Evento del boton "<<" de la ganancia del sistema """ enableIncGanancia() gananciaValue = int(lblGananciaValue.cget("text")) gananciaValue -= 5 if gananciaValue <= minGananciaValue: gananciaValue = minGananciaValue disableDecGanancia() lblGananciaValue.config(text=gananciaValue) def enableIncGanancia(): """ Permite habilitar los botones ">>" y ">" de ganancia """ btnIncGanancia.config(state="normal") btnIncGanancia2.config(state="normal") def enableDecGanancia(): """ Permite habilitar los botones "<<" y "<" de ganancia """ btnDecGanancia.config(state="normal") btnDecGanancia2.config(state="normal") def disableIncGanancia(): """ Permite deshabilitar los botones ">>" y ">" de ganancia """ btnIncGanancia.config(state="disable") btnIncGanancia2.config(state="disable") def disableDecGanancia(): """ Permite deshabilitar los botones "<<" y "<" de ganancia """ btnDecGanancia.config(state="disable") btnDecGanancia2.config(state="disable") """ Funciones botones para el valor de Vmax """ maxVMAXvalue = 5 minVMAXvalue = -20 def incVmax(): """ Evento del boton ">" de vmax """ enableDecVmax() vmaxValue = float(lblVmaxValue.cget("text")) vmaxValue += 0.1 if vmaxValue >= maxVMAXvalue: vmaxValue = maxVMAXvalue disableIncVmax() lblVmaxValue.config(text=str(round(vmaxValue,1))) def incVmax2(): """ Evento del boton ">>" de vmax """ enableDecVmax() vmaxValue = float(lblVmaxValue.cget("text")) vmaxValue += 1 if vmaxValue >= maxVMAXvalue: vmaxValue = maxVMAXvalue disableIncVmax() lblVmaxValue.config(text=str(round(vmaxValue,1))) def decVmax(): """ Evento del boton "<" de vmax """ enableIncVmax() vmaxValue = float(lblVmaxValue.cget("text")) vmaxValue -= 0.1 if vmaxValue <= minVMAXvalue: vmaxValue = minVMAXvalue disableDecVmax() if vmaxValue > float(lblVminValue.cget("text")): lblVmaxValue.config(text=str(round(vmaxValue,1))) def decVmax2(): """ Evento del boton "<<" de vmax """ enableIncVmax() vmaxValue = float(lblVmaxValue.cget("text")) vmaxValue -= 1 if vmaxValue <= minVMAXvalue: vmaxValue = minVMAXvalue disableDecVmax() if vmaxValue > float(lblVminValue.cget("text")): lblVmaxValue.config(text=str(round(vmaxValue,1))) def enableIncVmax(): """ Permite habilitar los botones ">>" y ">" de vmax """ btnIncVmax.config(state="normal") btnIncVmax2.config(state="normal") def enableDecVmax(): """ Permite habilitar los botones "<<" y "<" de vmax """ btnDecVmax.config(state="normal") btnDecVmax2.config(state="normal") def disableIncVmax(): """ Permite deshabilitar los botones ">>" y ">" de vmax """ btnIncVmax.config(state="disable") btnIncVmax2.config(state="disable") def disableDecVmax(): """ Permite deshabilitar los botones "<<" y "<" de vmax """ btnDecVmax.config(state="disable") btnDecVmax2.config(state="disable") """ Funciones botones para el valor de Vmin """ maxVMINValue = 0 minVMINValue = -40 def incVmin(): """ Evento del boton ">" de vmin """ enableDecVmin() VminValue = float(lblVminValue.cget("text")) VminValue += 0.1 if VminValue >= maxVMINValue: VminValue = maxVMINValue disableIncVmin() if VminValue < float(lblVmaxValue.cget("text")): lblVminValue.config(text=str(round(VminValue,1))) def incVmin2(): """ Evento del boton ">>" de vmin """ enableDecVmin() VminValue = float(lblVminValue.cget("text")) VminValue += 1 if VminValue >= maxVMINValue: VminValue = maxVMINValue disableIncVmin() if VminValue < float(lblVmaxValue.cget("text")): lblVminValue.config(text=str(round(VminValue,1))) def decVmin(): """ Evento del boton "<" de vmin """ enableIncVmin() VminValue = float(lblVminValue.cget("text")) VminValue -= 0.1 if VminValue <= minVMINValue: VminValue = minVMINValue disableDecVmin() lblVminValue.config(text=str(round(VminValue,1))) def decVmin2(): """ Evento del boton "<<" de vmin """ enableIncVmin() VminValue = float(lblVminValue.cget("text")) VminValue -= 1 if VminValue <= minVMINValue: VminValue = minVMINValue disableDecVmin() lblVminValue.config(text=str(round(VminValue,1))) def enableIncVmin(): """ Permite habilitar los botones ">>" y ">" de vmin """ btnIncVmin.config(state="normal") btnIncVmin2.config(state="normal") def enableDecVmin(): """ Permite habilitar los botones "<<" y "<" de vmin """ btnDecVmin.config(state="normal") btnDecVmin2.config(state="normal") def disableIncVmin(): """ Permite deshabilitar los botones ">>" y ">" de vmin """ btnIncVmin.config(state="disable") btnIncVmin2.config(state="disable") def disableDecVmin(): """ Permite deshabilitar los botones "<<" y "<" de vmin """ btnDecVmin.config(state="disable") btnDecVmin2.config(state="disable") """ Funciones para actualizar el modo (Reconstruction o Setup) en pantalla """ def btnReconstruccionClicked(): """ Evento del boton modo Reconstruccion """ global mode mode = "Reconstruccion" lblModeValue.config(text="Reconstrucción") btnReconstruccion.config(state='disabled') btnSetup.config(state='normal') def btnSetupClicked(): """ Evento del boton modo Setup """ global mode mode = "Setup" lblModeValue.config(text=mode) btnReconstruccion.config(state='normal') btnSetup.config(state='disabled') """ Funciones para obtener el vector de datos homogéneo """ def calibrar(): """ Evento del boton calibrar """ ImpetomC.actualizarVectorDeDatosHomogeneo() btnReset.config(state="normal") """ Funciones botones Saved Timed """ maxTimeValue= 120 minTimeValue = 0.5 def incTime(): """ Evento del boton ">" de tiempo entre imagenes guardadas """ enableDecTime() timeValue = float(lblSaveTimeValue.cget("text")) if timeValue == minTimeValue: timeValue = 1 else: timeValue += 1 if timeValue >= maxTimeValue: timeValue = maxTimeValue disbleIncTime() lblSaveTimeValue.config(text=str(round(timeValue))) def incTime2(): """ Evento del boton ">>" de tiempo entre imagenes guardadas """ enableDecTime() timeValue = float(lblSaveTimeValue.cget("text")) if timeValue == minTimeValue: timeValue = 5 else: timeValue += 5 if timeValue >= maxTimeValue: timeValue = maxTimeValue disbleIncTime() lblSaveTimeValue.config(text=str(round(timeValue))) def decTime(): """ Evento del boton "<" de tiempo entre imagenes guardadas """ enableIncTime() timeValue = float(lblSaveTimeValue.cget("text")) timeValue -= 1 if timeValue < minTimeValue: timeValue = minTimeValue lblSaveTimeValue.config(text=str(round(timeValue,1))) disableDecTime() else: lblSaveTimeValue.config(text=str(round(timeValue))) def decTime2(): """ Evento del boton "<<" de tiempo entre imagenes guardadas """ enableIncTime() timeValue = float(lblSaveTimeValue.cget("text")) timeValue -= 5 if timeValue < minTimeValue: timeValue = minTimeValue lblSaveTimeValue.config(text=str(round(timeValue,1)))#redondea para colocar 0.5 en pantalla disableDecTime() else: lblSaveTimeValue.config(text=str(round(timeValue))) def enableIncTime(): """ Permite habilitar los botones ">>" y ">" del tiempo entre imagenes guardadas """ btnIncTime.config(state="normal") btnIncTime2.config(state="normal") def enableDecTime(): """ Permite habilitar los botones "<<" y "<" del tiempo entre imagenes guardadas """ btnDecTime.config(state="normal") btnDecTime2.config(state="normal") def disbleIncTime(): """ Permite deshabilitar los botones ">>" y ">" del tiempo entre imagenes guardadas """ btnIncTime.config(state="disable") btnIncTime2.config(state="disable") def disableDecTime(): """ Permite deshabilitar los botones "<<" y "<" del tiempo entre imagenes guardadas """ btnDecTime.config(state="disable") btnDecTime2.config(state="disable") """ Funciones de los radioButtons de BP """ def enableScaleOptions(): """ Evento del radio button para habilitar las opciones del rango de escala """ global sclRangeEnable sclRangeEnable = True enableIncVmin() enableIncVmax() enableDecVmin() enableDecVmax() def disableScaleOptions(): """ Evento del radio button para deshabilitar las opciones del rango de escala """ global sclRangeEnable sclRangeEnable = False disableDecVmin() disableDecVmax() disableIncVmax() disableIncVmin() """ Función para el control del evento de cierre de la aplicación """ def onClose(): """ Evento de cierre de la aplicacion """ if tkinter.messagebox.askyesno("Salir","Está seguro que desea salir?"): global Reconstruir if Reconstruir: Reconstruir=False time.sleep(5)# esto es para que pueda finalizar el programa sin tirar error. Es por si se cierra el programa, con el programa updeteando la imagen root.destroy() """ Armado de la interfaz Como nota general, se uso para la escala de la pantalla 1200 (width) y 750 (height), por eso se ven esos números en todo el código de aquí en más. Esto es porque para la versión incial de la interfaz se utilizó una con ese tamaño y se logró colocar todos los widgets quedando la interfaz agradable a la vista """ if __name__ == '__main__': root = Tk() root.title("Impetom-C app") screenWidth = root.winfo_screenwidth() screenHeight = root.winfo_screenheight() rootSize = str(screenWidth) + "x" + str(screenHeight) root.geometry(rootSize) root.protocol("WM_DELETE_WINDOW", onClose) # manejo del evento de cierre por la cruz de la interfaz root.resizable(width=False, height=False) # el usuario no puede cambiar el tamaño de la ventana """ Info Impetom + logo fing """ # Se agrega imagen de fondo de la app bg = PhotoImage(file="fondo_Impetom.png") # color azul fondo #2b70e4 amarillo #eccc6e # Create Canvas canvas1 = Canvas(root, width=screenWidth, height=screenHeight) canvas1.place(x=0, y=0) canvas1.create_image((0 / 1200) * screenWidth, 0, image=bg, anchor="nw") """ Datos del paciente #f00 es el color rojo para cualquier SO """ lblPatient = Label(root, text="Datos del paciente", bg='#2b70e4', fg='white', font=("Helvetica", 12, "bold")) lblPatient.place(x=(30 / 1200) * screenWidth, y=(20 / 750) * screenHeight) lblDate = Label(root, text="Fecha: " + str(date.today().strftime("%b-%d-%Y")), bg='#2b70e4', fg='white', font=("Helvetica", 10, "bold")) lblDate.place(x=(330 / 1200) * screenWidth, y=(20 / 750) * screenHeight) lblName = Label(root, text="Nombre:", bg='#2b70e4', fg='white', font=("Helvetica", 10, "bold")) lblName.place(x=(50 / 1200) * screenWidth, y=(50 / 750) * screenHeight) txtName = Text(root, width=30, height=1) txtName.place(x=(105 / 1200) * screenWidth, y=(50 / 750) * screenHeight) lblNameError = Label(root, fg='red', text="Este campo es obligatorio", bg='#2b70e4', font=("Helvetica", 8, "bold")) lblNameError.place(x=(100 / 1200) * screenWidth, y=(75 / 750) * screenHeight) lblCi = Label(root, text="CI:", bg='#2b70e4', fg='white', font=("Helvetica", 10, "bold")) lblCi.place(x=(50 / 1200) * screenWidth, y=(100 / 750) * screenHeight) txtCi = Text(root, width=15, height=1) txtCi.place(x=(100 / 1200) * screenWidth, y=(100 / 750) * screenHeight) lblCiError = Label(root, fg='red', text="Este campo es obligatorio", bg='#2b70e4', font=("Helvetica", 8, "bold")) lblCiError.place(x=(100 / 1200) * screenWidth, y=(125 / 750) * screenHeight) lblSexoBiologico = Label(root, text="Sexo:", bg='#2b70e4', fg='white', font=("Helvetica", 10, "bold")) lblSexoBiologico.place(x=(310 / 1200) * screenWidth, y=(50 / 750) * screenHeight) cmbBioSex = tkinter.ttk.Combobox(root, values=['Seleccionar', 'M', 'F', 'Otro'], state='readonly', width=10) cmbBioSex.place(x=(350 / 1200) * screenWidth, y=(50 / 750) * screenHeight) lblBioSexError = Label(root, text="Este campo es obligatorio", fg='red', bg='#2b70e4', font=("Helvetica", 8, "bold")) lblBioSexError.place(x=(315 / 1200) * screenWidth, y=(75 / 750) * screenHeight) cmbBioSex.current(0) lblBirthDate = Label(root, text="Fecha de nacimiento:", bg='#2b70e4', fg='white', font=("Helvetica", 10, "bold")) lblBirthDate.place(x=(215 / 1200) * screenWidth, y=(100 / 750) * screenHeight) txtBirthDate = Text(root, width=10, height=1) txtBirthDate.place(x=(350 / 1200) * screenWidth, y=(100 / 750) * screenHeight) lblBirthDateError = Label(root, text="Formato : dd-mm-yyyy", fg='red', bg='#2b70e4', font=("Helvetica", 8, "bold")) lblBirthDateError.place(x=(315 / 1200) * screenWidth, y=(125 / 750) * screenHeight) """ Imagen inicial en la app """ photo = ImageTk.PhotoImage(img) lblImg = Label(root, image=photo, width=(700 / 1200) * screenWidth, height=(500 / 750) * screenHeight) lblImg.place(x=(445 / 1200) * screenWidth, y=(175 / 750) * screenHeight) """ botones Start, Stop, Calibrar y Reset """ btnStart = Button(root, text="Start", padx=15, pady=2, command=btnStartClicked) btnStart.place(x=(1030 / 1200) * screenWidth, y=(690 / 750) * screenHeight) btnStop = Button(root, text="Stop", padx=10, pady=2, command=btnStopClicked, state='disable') btnStop.place(x=(1090 / 1200) * screenWidth, y=(690 / 750) * screenHeight) btnCalibrar = Button(root, text="Calibrar", command=calibrar) btnCalibrar.place(x=(400 / 1200) * screenWidth, y=(690 / 750) * screenHeight) btnReset = Button(root, text="Reset", command=btnResetClicked, state='disable') btnReset.place(x=(1100 / 1200) * screenWidth, y=(145 / 750) * screenHeight) """ Control de modo de cambio de modo """ lblMode = Label(root, text="Modo: ", bg='#2b70e4', font=("Helvetica", 12, "bold")) lblMode.place(x=(140 / 1200) * screenWidth, y=(170 / 750) * screenHeight) lblModeValue = Label(root, text=mode, bg='#2b70e4', font=("Helvetica", 12)) lblModeValue.place(x=(190 / 1200) * screenWidth, y=(170 / 750) * screenHeight) btnReconstruccion = Button(root, text="Reconstrucción", command=btnReconstruccionClicked, font=("Helvetica", 10, "bold")) btnReconstruccion.place(x=(110 / 1200) * screenWidth, y=(195 / 750) * screenHeight) btnSetup = Button(root, text="Setup", padx=10, command=btnSetupClicked, state='disable', font=("Helvetica", 10, "bold")) btnSetup.place(x=(210 / 1200) * screenWidth, y=(195 / 750) * screenHeight) lblModeMessage = Label(root, fg='#f00', bg='white') lblModeMessage.place(x=(80 / 1200) * screenWidth, y=(225 / 750) * screenHeight) """ Opciones para la reconstrucción Primero el valor p """ lblImgOptions = Label(root, text="Opciones de imagen", font=("Helvetica", 10, "bold"), bg='white') lblImgOptions.place(x=(130 / 1200) * screenWidth, y=(245 / 750) * screenHeight) lblp = Label(root, text="p", bg='white') lblp.place(x=(177 / 1200) * screenWidth, y=(270 / 750) * screenHeight) initialPValue = "0.2" lblpRangeValue = Label(root, text=initialPValue, bg='white') # p=0.25 para setup lblpRangeValue.place(x=(175 / 1200) * screenWidth, y=(295 / 750) * screenHeight) btnIncpRange = Button(root, text=">", command=incPRange) btnIncpRange.place(x=(250 / 1200) * screenWidth, y=(295 / 750) * screenHeight) btnIncpRange2 = Button(root, text=">>", command=incPRange2) btnIncpRange2.place(x=(275 / 1200) * screenWidth, y=(295 / 750) * screenHeight) btnDecpRange = Button(root, text="<", command=decPRange) btnDecpRange.place(x=(100 / 1200) * screenWidth, y=(295 / 750) * screenHeight) btnDecpRange2 = Button(root, text="<<", command=decPRange2) btnDecpRange2.place(x=(67 / 1200) * screenWidth, y=(295 / 750) * screenHeight) """ Control para la frecuencia (ganancia) """ lblGanancia = Label(root, text="Ganancia", bg='white') lblGanancia.place(x=(160 / 1200) * screenWidth, y=(330 / 750) * screenHeight) initialGValue = "-10" lblGananciaValue = Label(root, text=initialGValue, bg='white') lblGananciaValue.place(x=(175 / 1200) * screenWidth, y=(355 / 750) * screenHeight) btnIncGanancia = Button(root, text=">", command=incGanancia) btnIncGanancia.place(x=(250 / 1200) * screenWidth, y=(355 / 750) * screenHeight) btnIncGanancia2 = Button(root, text=">>", command=incGanancia2) btnIncGanancia2.place(x=(275 / 1200) * screenWidth, y=(355 / 750) * screenHeight) btnDecGanancia = Button(root, text="<", command=decGanancia) btnDecGanancia.place(x=(100 / 1200) * screenWidth, y=(355 / 750) * screenHeight) btnDecGanancia2 = Button(root, text="<<", command=decGanancia2) btnDecGanancia2.place(x=(67 / 1200) * screenWidth, y=(355 / 750) * screenHeight) """ Control del rango de escala """ lblSclRangeOptions = Label(root, text="Control de rango de escala", font=("Helvetica", 10, "bold"), bg='white') lblSclRangeOptions.place(x=(110 / 1200) * screenWidth, y=(400 / 750) * screenHeight) rbtnSclOptionsEnable = Radiobutton(root, text="On", variable=0, value=1, command=enableScaleOptions, bg='white') rbtnSclOptionsEnable.place(x=(280 / 1200) * screenWidth, y=(400 / 750) * screenHeight) rbtnSclOptionsDisable = Radiobutton(root, text="Off", variable=0, value=2, command=disableScaleOptions, bg='white') rbtnSclOptionsDisable.place(x=(320 / 1200) * screenWidth, y=(400 / 750) * screenHeight) rbtnSclOptionsDisable.select() """ Control Vmax """ lblVmax = Label(root, text=" Valor máximo", bg='white') lblVmax.place(x=(145 / 1200) * screenWidth, y=(425 / 750) * screenHeight) initialVmaxValue = "0.5" lblVmaxValue = Label(root, text=initialVmaxValue, bg='white') lblVmaxValue.place(x=(175 / 1200) * screenWidth, y=(450 / 750) * screenHeight) btnIncVmax = Button(root, text=">", command=incVmax) btnIncVmax.place(x=(250 / 1200) * screenWidth, y=(450 / 750) * screenHeight) btnIncVmax2 = Button(root, text=">>", command=incVmax2) btnIncVmax2.place(x=(275 / 1200) * screenWidth, y=(450 / 750) * screenHeight) btnDecVmax = Button(root, text="<", command=decVmax) btnDecVmax.place(x=(100 / 1200) * screenWidth, y=(450 / 750) * screenHeight) btnDecVmax2 = Button(root, text="<<", command=decVmax2) btnDecVmax2.place(x=(67 / 1200) * screenWidth, y=(450 / 750) * screenHeight) """ Control Vmin """ lblVmin = Label(root, text=" Valor mínimo", bg='white') lblVmin.place(x=(145 / 1200) * screenWidth, y=(480 / 750) * screenHeight) initialVminValue = "-5.5" lblVminValue = Label(root, text=initialVminValue, bg='white') lblVminValue.place(x=(175 / 1200) * screenWidth, y=(510 / 750) * screenHeight) btnIncVmin = Button(root, text=">", command=incVmin) btnIncVmin.place(x=(250 / 1200) * screenWidth, y=(510 / 750) * screenHeight) btnIncVmin2 = Button(root, text=">>", command=incVmin2) btnIncVmin2.place(x=(275 / 1200) * screenWidth, y=(510 / 750) * screenHeight) btnDecVmin = Button(root, text="<", command=decVmin) btnDecVmin.place(x=(100 / 1200) * screenWidth, y=(510 / 750) * screenHeight) btnDecVmin2 = Button(root, text="<<", command=decVmin2) btnDecVmin2.place(x=(67 / 1200) * screenWidth, y=(510 / 750) * screenHeight) """ Control del Modelo """ lblContorno = Label(root, text="Especificaciones de contorno", font=("Helvetica", 10, "bold"), bg='white') lblContorno.place(x=(110 / 1200) * screenWidth, y=(550 / 750) * screenHeight) lblModel = Label(root, text="Forma", bg='white') lblModel.place(x=(160 / 1200) * screenWidth, y=(575 / 750) * screenHeight) cmbModel = tkinter.ttk.Combobox(root, values=['Thorax', 'Circle'], state='readonly') cmbModel.place(x=(120 / 1200) * screenWidth, y=(600 / 750) * screenHeight) cmbModel.current(0) # el valor inicial de comboBox es Thorax """ Control de Medida """ lblMedida = Label(root, text="Perímetro (mm)", bg='white') lblMedida.place(x=(260 / 1200) * screenWidth, y=(575 / 750) * screenHeight) txtMedida = Text(root, width=4, height=1) txtMedida.place(x=(280 / 1200) * screenWidth, y=(600 / 750) * screenHeight) lblMedidaError = Label(root, text="Campo obligatorio", fg='#f00', bg='white') lblMedidaError.place(x=(265 / 1200) * screenWidth, y=(620 / 750) * screenHeight) """ Control de Medida_Z """ lblMedidaZ = Label(root, text="Altura (mm)", bg='white') lblMedidaZ.place(x=(350 / 1200) * screenWidth, y=(575 / 750) * screenHeight) txtMedidaZ = Text(root, width=4, height=1) txtMedidaZ.place(x=(360 / 1200) * screenWidth, y=(600 / 750) * screenHeight) lblMedidaZError = Label(root, text="Campo obligatorio", fg='#f00', bg='white') lblMedidaZError.place(x=(345 / 1200) * screenWidth, y=(550 / 750) * screenHeight) """ Control de tiempos para guardado de imágenes para historia clínica """ lblSaveTime = Label(root, text="Tiempo de guardado (min)", font=("Helvetica", 10, "bold"), bg='white') lblSaveTime.place(x=(100 / 1200) * screenWidth, y=(635 / 750) * screenHeight) initialSaveTimeValue = "5" lblSaveTimeValue = Label(root, text=initialSaveTimeValue, bg='white') lblSaveTimeValue.place(x=(175 / 1200) * screenWidth, y=(665 / 750) * screenHeight) btnIncTime = Button(root, text=">", command=incTime) btnIncTime.place(x=(250 / 1200) * screenWidth, y=(665 / 750) * screenHeight) btnIncTime2 = Button(root, text=">>", command=incTime2) btnIncTime2.place(x=(275 / 1200) * screenWidth, y=(665 / 750) * screenHeight) btnDecTime = Button(root, text="<", command=decTime) btnDecTime.place(x=(100 / 1200) * screenWidth, y=(665 / 750) * screenHeight) btnDecTime2 = Button(root, text="<<", command=decTime2) btnDecTime2.place(x=(67 / 1200) * screenWidth, y=(665 / 750) * screenHeight) lblTimeError = Label(root, text="", fg='#f00', bg='white') lblTimeError.place(x=(100 / 1200) * screenWidth, y=(700 / 750) * screenHeight) """ Por problemas con Arduino al inicio de la aplicación #2b70e4es el color azul de la imagen del banner """ lblError = Label(root, text="", bg='#2b70e4', font=("Helvetica", 10, "bold"), fg="red") lblError.place(x=(440 / 1200) * screenWidth, y=(150 / 750) * screenHeight) disableScaleOptions() # Comienzo el programa con la escala deshabilitada try: ImpetomC.startUp() arduinoImpetom = 1 # Indicador que arduinoImpetom esta conectado except ImpetomCError as e: lblError.config(text=str(e) + " Revise la conexión al dispositivo y presione Start", bg='white') arduinoImpetom = 0 root.mainloop()