0% encontró este documento útil (0 votos)
3 vistas17 páginas

Aplicación de Recetario en Tkinter

Codigo
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
3 vistas17 páginas

Aplicación de Recetario en Tkinter

Codigo
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd

import tkinter as tk

from tkinter import scrolledtext, filedialog, messagebox

import sqlite3

try:

from PIL import Image, ImageTk

PIL_DISPONIBLE = True

except Exception:

PIL_DISPONIBLE = False

# ----------------- Base de datos -----------------

def inicializar_db():

conn = [Link]("[Link]")

cursor = [Link]()

[Link]("""

CREATE TABLE IF NOT EXISTS recetas (

id INTEGER PRIMARY KEY AUTOINCREMENT,

categoria TEXT NOT NULL,

nombre TEXT NOT NULL,

ingredientes TEXT,

preparacion TEXT,

imagen TEXT

""")

[Link]()

[Link]()

def guardar_receta(categoria, nombre, ingredientes, preparacion, imagen):

conn = [Link]("[Link]")
cursor = [Link]()

[Link](

"INSERT INTO recetas (categoria, nombre, ingredientes, preparacion, imagen) VALUES (?, ?, ?, ?, ?)",

(categoria, nombre, ingredientes, preparacion, imagen)

[Link]()

[Link]()

def obtener_recetas(categoria):

conn = [Link]("[Link]")

cursor = [Link]()

[Link]("SELECT id, nombre FROM recetas WHERE categoria = ? ORDER BY nombre COLLATE
NOCASE", (categoria,))

recetas = [Link]()

[Link]()

return recetas

def obtener_receta_por_id(receta_id):

conn = [Link]("[Link]")

cursor = [Link]()

[Link]("SELECT categoria, nombre, ingredientes, preparacion, imagen FROM recetas WHERE id = ?",
(receta_id,))

receta = [Link]()

[Link]()

return receta

def borrar_receta(receta_id):

conn = [Link]("[Link]")

cursor = [Link]()

[Link]("DELETE FROM recetas WHERE id = ?", (receta_id,))


[Link]()

[Link]()

# ----------------- Utilidades -----------------

def limpiar_ventana(root):

for w in root.winfo_children():

[Link]()

def parse_cantidad(token):

token = [Link]()

if not token:

return None

if "/" in token:

try:

a, b = [Link]("/", 1)

return float(a) / float(b)

except Exception:

return None

try:

return float(token)

except Exception:

return None

def escalar_ingredientes(texto_ingredientes, factor):

resultado = []

for linea in texto_ingredientes.splitlines():

linea = [Link]()

if not linea:

continue
partes = [Link]()

cantidad_val = parse_cantidad(partes[0]) if partes else None

if cantidad_val is not None:

nueva = cantidad_val * factor

if abs(nueva - round(nueva)) < 1e-9:

nueva_str = str(int(round(nueva)))

else:

nueva_str = f"{nueva:.3f}".rstrip("0").rstrip(".")

[Link](f"{nueva_str} {' '.join(partes[1:])}")

else:

[Link](linea)

return "\n".join(resultado)

# ----------------- Aplicación -----------------

class RecetarioApp:

def __init__(self, root):

[Link] = root

[Link]("Recetario")

[Link]("900x800")

[Link](bg="#f7f7f7")

[Link] = {

"Carnes": "#b71c1c",

"Lácteos": "#64b5f6",

"Frutas": "#4caf50",

"Cereales": "#ff9800"

self.categoria_actual = None
inicializar_db()

self.pantalla_bienvenida()

def pantalla_bienvenida(self):

limpiar_ventana([Link])

[Link]([Link], text="¡Bienvenidos al Recetario!", font=("Arial", 28, "bold"),

bg="#f7f7f7", fg="#222").pack(pady=40)

[Link]([Link], text="🚀 Iniciar", width=25, height=3,

font=("Arial", 16, "bold"), bg="#b31408", fg="white",

command=self.menu_principal).pack(pady=20)

#-------------------------

def menu_principal(self):

limpiar_ventana([Link])

[Link]([Link], text="Recetario", font=("Arial", 26, "bold"),

bg="#f7f7f7", fg="#222").pack(pady=18)

botones = [Link]([Link], bg="#f7f7f7")

[Link](pady=5)

[Link](botones, text="📖 Ver recetario", width=22, height=2,

font=("Arial", 14, "bold"), bg="#4CAF50", fg="white",

command=self.mostrar_recetario).grid(row=0, column=0, padx=8, pady=8)

[Link](botones, text="➕ Agregar receta", width=22, height=2,

font=("Arial", 14, "bold"), bg="#2196F3", fg="white",

command=self.agregar_receta).grid(row=1, column=0, padx=8, pady=8)

[Link](botones, text="❌ Salir", width=22, height=2,

font=("Arial", 14, "bold"), bg="#f44336", fg="white",


command=[Link]).grid(row=2, column=0, padx=8, pady=8)

def mostrar_recetario(self):

limpiar_ventana([Link])

[Link]([Link], text="Menú de recetas", font=("Arial", 22, "bold"), bg="#ffffff").pack(pady=15)

cont = [Link]([Link], bg="#ffffff")

[Link](pady=10, padx=20)

for i, (categoria, color) in enumerate([Link]()):

[Link](cont, text=categoria, font=("Arial", 14, "bold"),

bg=color, fg="white", width=20, height=2,

command=lambda c=categoria: self.abrir_categoria(c)).grid(row=i//3, column=i%3, padx=8,


pady=8)

[Link]([Link], text="⬅️Volver", font=("Arial", 12),

bg="#cccccc", command=self.menu_principal).pack(pady=10)

[Link]([Link], text="❌ Salir", font=("Arial", 12),

bg="#f44336", fg="white", command=[Link]).pack(pady=10)

def abrir_categoria(self, nombre):

limpiar_ventana([Link])

self.categoria_actual = nombre

[Link]([Link], text=f"Categoría: {nombre}", font=("Arial", 22, "bold"), bg="#ffffff").pack(pady=15)

recetas = obtener_recetas(nombre)

lista_frame = [Link]([Link], bg="#ffffff")

lista_frame.pack(pady=6)

if recetas:
for receta_id, nombre_receta in recetas:

[Link](lista_frame, text=nombre_receta, font=("Arial", 14),

bg="#eeeeee", fg="#333", width=32, height=2,

command=lambda rid=receta_id: self.mostrar_receta(rid)).pack(pady=6)

else:

[Link]([Link], text="No hay recetas en esta categoría.", font=("Arial", 12),

bg="#ffffff", fg="red").pack(pady=10)

[Link]([Link], text="⬅️Volver", font=("Arial", 12),

bg="#cccccc", command=self.mostrar_recetario).pack(pady=10)

[Link]([Link], text="❌ Salir", font=("Arial", 12),

bg="#f44336", fg="white", command=[Link]).pack(pady=10)

def mostrar_receta(self, receta_id):

limpiar_ventana([Link])

data = obtener_receta_por_id(receta_id)

if not data:

[Link]([Link], text="Receta no encontrada.", fg="red").pack(pady=10)

[Link]([Link], text="⬅️Volver", command=lambda:


self.abrir_categoria(self.categoria_actual)).pack()

return

categoria, nombre, ingredientes, preparacion, imagen = data

[Link]([Link], text=nombre, font=("Arial", 22, "bold"), bg="#ffffff").pack(pady=10)

acciones = [Link]([Link], bg="#ffffff")

[Link](pady=8)

[Link](acciones, text="📜 Ver procedimiento", font=("Arial", 12),


bg="#2196F3", fg="white",

command=lambda: self.ver_procedimiento(preparacion)).grid(row=0, column=0, padx=6, pady=6)

[Link](acciones, text="📊 Calcular cantidades", font=("Arial", 12),

bg="#4CAF50", fg="white",

command=lambda: self.calcular_view(ingredientes or "")).grid(row=0, column=1, padx=6, pady=6)

[Link](acciones, text=" Borrar receta", font=("Arial", 12),

bg="#f44336", fg="white",

command=lambda: self.confirmar_borrado(receta_id)).grid(row=0, column=2, padx=6, pady=6)

[Link](acciones, text="❌ Salir", font=("Arial", 12),

bg="#f44336", fg="white",

command=[Link]).grid(row=0, column=3, padx=6, pady=6)

card = [Link]([Link], bg="#fffbea", bd=2, relief="ridge")

[Link](pady=15, padx=20, fill="x")

[Link](card, text="Ingredientes:", font=("Arial", 14, "bold"), bg="#fffbea").pack(pady=6)

[Link](card, text=ingredientes or "—", font=("Arial", 12), bg="#fffbea",

justify="left", anchor="w").pack(pady=4, padx=8)

if imagen and PIL_DISPONIBLE:

try:

img = [Link](imagen)

max_w, max_h = 500, 350

[Link]((max_w, max_h))

photo = [Link](img)

lbl_img = [Link]([Link], image=photo, bg="#ffffff")


lbl_img.photo = photo

lbl_img.pack(pady=12)

except Exception:

[Link]([Link], text="No se pudo cargar la imagen.", fg="red", bg="#ffffff").pack(pady=5)

[Link]([Link], text="⬅️Volver", font=("Arial", 12),

bg="#cccccc", command=lambda: self.abrir_categoria(self.categoria_actual)).pack(pady=10)

def ver_procedimiento(self, preparacion):

limpiar_ventana([Link])

[Link]([Link], text="Procedimiento", font=("Arial", 22, "bold"), bg="#ffffff").pack(pady=10)

texto = [Link]([Link], width=100, height=28, font=("Arial", 12))

[Link]([Link], (preparacion or "—"))

[Link](state="disabled")

[Link](pady=12)

[Link]([Link], text="⬅️Volver", font=("Arial", 12),

bg="#cccccc", command=lambda: self.abrir_categoria(self.categoria_actual)).pack(pady=20)

def confirmar_borrado(self, receta_id):

resp = [Link]("Confirmar borrado", "¿Seguro que deseas eliminar esta receta?")

if resp:

borrar_receta(receta_id)

self.abrir_categoria(self.categoria_actual)

def calcular_view(self, ingredientes):

limpiar_ventana([Link])

[Link]([Link], text="Calcular cantidades", font=("Arial", 22, "bold"), bg="#ffffff").pack(pady=10)

contenedor = [Link]([Link], bg="#ffffff")


[Link](fill="both", expand=True)

canvas = [Link](contenedor, bg="#ffffff", highlightthickness=0)

scroll_y = [Link](contenedor, orient="vertical", command=[Link])

marco = [Link](canvas, bg="#ffffff")

[Link]("<Configure>", lambda e: [Link](scrollregion=[Link]("all")))

canvas.create_window((0, 0), window=marco, anchor="nw")

[Link](yscrollcommand=scroll_y.set)

[Link](side="left", fill="both", expand=True)

scroll_y.pack(side="right", fill="y")

box = [Link](marco, bg="#ffffff")

[Link](pady=8)

[Link](box, text="Factor directo (ej. 2 para duplicar):", font=("Arial", 12), bg="#ffffff")\

.grid(row=0, column=0, sticky="w", padx=4, pady=4)

factor_entry = [Link](box, width=10, font=("Arial", 12))

factor_entry.grid(row=0, column=1, padx=4, pady=4)

[Link](box, text="Base (ej. 1 litro):", font=("Arial", 12), bg="#ffffff")\

.grid(row=1, column=0, sticky="w", padx=4, pady=4)

base_entry = [Link](box, width=10, font=("Arial", 12))

base_entry.grid(row=1, column=1, padx=4, pady=4)

[Link](box, text="Deseado (ej. 2 litros):", font=("Arial", 12), bg="#ffffff")\

.grid(row=2, column=0, sticky="w", padx=4, pady=4)

deseado_entry = [Link](box, width=10, font=("Arial", 12))


deseado_entry.grid(row=2, column=1, padx=4, pady=4)

fila_botones = [Link](marco, bg="#ffffff")

fila_botones.pack(pady=8)

def mostrar_explicacion():

mensaje = (

"📘 Cómo funciona el cálculo:\n\n"

"1) Factor directo: 2 duplica, 0.5 reduce a la mitad.\n"

"2) Base/Deseado: si base=1 litro y deseado=2 litros → factor=2.\n\n"

"⚠️No convierte unidades; solo escala números."

[Link]("¿Cómo funciona?", mensaje)

result_area = [Link](marco, width=100, height=24, font=("Arial", 12))

result_area.pack(pady=12)

def aplicar_calculo():

factor = None

fd = factor_entry.get().strip()

if fd:

try:

factor = float(fd)

except Exception:

factor = None

if factor is None:

try:

base = float(base_entry.get().strip())

deseado = float(deseado_entry.get().strip())
if base > 0:

factor = deseado / base

except Exception:

pass

result_area.config(state="normal")

result_area.delete("1.0", [Link])

if factor is None:

result_area.insert([Link], "⚠️Ingresa un factor válido o base y deseado.\n")

else:

escalado = escalar_ingredientes(ingredientes, factor)

result_area.insert([Link], f"✅ Factor aplicado: {factor}\n\n{escalado}")

result_area.config(state="disabled")

[Link](fila_botones, text="📊 Calcular cantidades", font=("Arial", 12),

bg="#4CAF50", fg="white", command=aplicar_calculo).grid(row=0, column=0, padx=6, pady=6)

[Link](fila_botones, text="¿Cómo funciona?", font=("Arial", 12),

bg="#FF9800", fg="white", command=mostrar_explicacion).grid(row=0, column=1, padx=6, pady=6)

[Link](fila_botones, text="❌ Salir", font=("Arial", 12),

bg="#f44336", fg="white", command=[Link]).grid(row=0, column=2, padx=6, pady=6)

[Link](marco, text="⬅️Volver", font=("Arial", 12),

bg="#cccccc", command=lambda: self.abrir_categoria(self.categoria_actual)).pack(pady=10)

def agregar_receta(self):

limpiar_ventana([Link])
[Link]([Link], text="Agregar receta", font=("Arial", 22, "bold"), bg="#ffffff").pack(pady=15)

form = [Link]([Link], bg="#ffffff")

[Link](pady=8)

# --- Menú de categoría + botones arriba ---

fila_superior = [Link](form, bg="#ffffff")

fila_superior.grid(row=0, column=0, columnspan=2, pady=4)

[Link](fila_superior, text="Categoría:", font=("Arial", 12), bg="#ffffff").pack(side="left", padx=(0, 6))

categorias_opciones = ["Carnes", "Cereales", "Frutas", "Lácteos"]

categoria_var = [Link](value=categorias_opciones[0])

categoria_menu = [Link](fila_superior, categoria_var, *categorias_opciones)

categoria_menu.config(font=("Arial", 12), bg="#eeeeee")

categoria_menu.pack(side="left", padx=6)

[Link](fila_superior, text="Generar campos", font=("Arial", 12),

bg="#FF9800", fg="white", command=lambda: generar_campos()).pack(side="left", padx=6)

[Link](fila_superior, text="⬅️Volver", font=("Arial", 12),

bg="#cccccc", command=self.menu_principal).pack(side="left", padx=6)

[Link](fila_superior, text="❌ Salir", font=("Arial", 12),

bg="#d42114", fg="white", command=[Link]).pack(side="left", padx=6)

[Link](form, text="Nombre de la receta:", font=("Arial", 12), bg="#ffffff").grid(row=1, column=0,


sticky="w", padx=4, pady=4)

nombre_entry = [Link](form, width=30, font=("Arial", 12))

nombre_entry.grid(row=1, column=1, padx=4, pady=4)


[Link](form, text="¿Cuántos ingredientes?", font=("Arial", 12), bg="#ffffff").grid(row=2, column=0,
sticky="w", padx=4, pady=4)

num_entry = [Link](form, width=6, font=("Arial", 12))

num_entry.grid(row=2, column=1, padx=4, pady=4)

imagen_path = [Link](value="")

campos = []

# --- Área con scroll para campos dinámicos ---

campos_frame = [Link]([Link], bg="#ffffff")

campos_frame.pack(pady=10, padx=20, fill="both", expand=True)

canvas = [Link](campos_frame, bg="#ffffff", highlightthickness=0)

scroll_y = [Link](campos_frame, orient="vertical", command=[Link])

inner = [Link](canvas, bg="#ffffff")

[Link]("<Configure>", lambda e: [Link](scrollregion=[Link]("all")))

canvas.create_window((0, 0), window=inner, anchor="nw")

[Link](yscrollcommand=scroll_y.set)

[Link](side="left", fill="both", expand=True)

scroll_y.pack(side="right", fill="y")

def seleccionar_imagen():

ruta = [Link](

title="Seleccionar imagen",

filetypes=[("Imágenes", ".jpg *.jpeg *.png *.gif"), ("Todos", ".*")]

if ruta:

imagen_path.set(ruta)
[Link](inner, text=f"Imagen seleccionada: {ruta}", bg="#ffffff", fg="green").pack(pady=4)

def guardar_final():

categoria = categoria_var.get()

nombre = nombre_entry.get().strip()

if not categoria or not nombre:

[Link]("Error", "Categoría y nombre son obligatorios.")

return

lines = []

for ing_e, cant_e in campos:

ing = ing_e.get().strip()

cant = cant_e.get().strip()

if ing:

linea = (cant + " " + ing).strip()

[Link](linea)

ingredientes_txt = "\n".join(lines)

preparacion_txt = prep_text.get("1.0", [Link]).strip()

ruta_imagen = imagen_path.get()

try:

guardar_receta(categoria, nombre, ingredientes_txt, preparacion_txt, ruta_imagen)

[Link]("OK", "Receta guardada correctamente.")

self.menu_principal()

except Exception as e:

[Link]("Error", f"No se pudo guardar la receta.\n{e}")

def generar_campos():
for w in inner.winfo_children():

[Link]()

[Link]()

try:

n = int(num_entry.get())

if n <= 0 or n > 30:

raise ValueError

except Exception:

[Link](inner, text="Ingresa un número válido entre 1 y 30.", fg="red", bg="#ffffff").pack(pady=6)

return

[Link](inner, text="Ingredientes", font=("Arial", 14, "bold"), bg="#ffffff").pack(pady=6)

for i in range(n):

fila = [Link](inner, bg="#ffffff")

[Link](fill="x", padx=4, pady=4)

[Link](fila, text=f"{i+1}. Ingrediente:", font=("Arial", 11), bg="#ffffff").grid(row=0, column=0,


sticky="w")

ing_entry = [Link](fila, width=30, font=("Arial", 11))

ing_entry.grid(row=0, column=1, padx=4)

[Link](fila, text="Cantidad:", font=("Arial", 11), bg="#ffffff").grid(row=0, column=2, sticky="w",


padx=(12,0))

cant_entry = [Link](fila, width=12, font=("Arial", 11))

cant_entry.grid(row=0, column=3, padx=4)

[Link](fila, text="Ejemplos: 2, 1.5, 1/2", font=("Arial", 9), fg="#666", bg="#ffffff").grid(row=0,


column=4, padx=6)
[Link]((ing_entry, cant_entry))

# --- Botones útiles debajo de ingredientes ---

[Link](inner, text="Seleccionar imagen", font=("Arial", 12),

bg="#9C27B0", fg="white", command=seleccionar_imagen).pack(pady=6)

[Link](inner, text="Guardar receta", font=("Arial", 12),

bg="#4CAF50", fg="white", command=guardar_final).pack(pady=6)

[Link](inner, text="Preparación", font=("Arial", 14, "bold"), bg="#ffffff").pack(pady=8)

global prep_text

prep_text = [Link](inner, width=100, height=15, font=("Arial", 12))

prep_text.pack(pady=6)

# ----------------- Ejecutar -----------------

if __name__ == "__main__":

root = [Link]()

app = RecetarioApp(root)

[Link]()

También podría gustarte