He aquí un simple editor de archivos de texto escrito en Python con el módulo estándar tkinter. El programa está compuesto por una simple ventana, una barra de menús y un control tk.Text para mostrar el contenido de los archivos. Para permitir al usuario examinar los archivos se usa el módulo estándar tkinter.filedialog. Los archivos de texto se escriben y leen vía la clase estándar pathlib.Path. El código incluye anotaciones de tipos, por lo cual requiere Python 3.9 o superior. El resto está suficientemente comentado a continuación.
from typing import Optional
from tkinter import filedialog, messagebox
from pathlib import Path
import tkinter as tk
class Notepad(tk.Tk):
def __init__(self) -> None:
super().__init__()
self.title("Bloc de notas")
self.geometry("800x500")
# Barra de menú.
self.menubar = tk.Menu()
self.file_menu = tk.Menu(tearoff=False)
self.file_menu.add_command(label="Nuevo", command=self.new)
self.file_menu.add_command(label="Abrir", command=self.open)
self.file_menu.add_command(label="Guardar", command=self.save)
self.file_menu.add_command(
label="Guardar como...",
command=self.save_as
)
self.menubar.add_cascade(menu=self.file_menu, label="Archivo")
self.config(menu=self.menubar)
# Control principal para editar el texto de un archivo.
self.text = tk.Text()
self.text.pack(expand=True, fill=tk.BOTH)
# El atributo `current_file` contiene la ruta del archivo
# que se está editando actualmente o `None` si aún no se
# ha guardado el archivo.
self.current_file: Optional[Path] = None
# Tipos de archivos que aparecerán en los cuadros para
# abrir o guardar un archivo.
self.filetypes: tuple[tuple[str, str], ...] = (
("Archivo de texto", "*.txt"),
("Todos los archivos", "*.*")
)
# Reemplazar el mecanismo de cierre por defecto de Tk
# para poder guardar el archivo antes de terminar
# el programa.
self.protocol("WM_DELETE_WINDOW", self.close)
def close(self) -> None:
if not self.can_continue():
return
# Destruir la ventana.
self.destroy()
def set_current_file(self, current_file: Path) -> None:
self.current_file = current_file
# Cuando cambia el archivo actual se actualiza
# el título con el nombre del nuevo archivo.
self.title(self.current_file.name + " - Bloc de notas")
def can_continue(self) -> bool:
# Si se hicieron modificaciones al texto, pedir la
# confirmación al usuario.
if self.text.edit_modified():
result = messagebox.askyesnocancel(
title="Cambios sin guardar",
message="¿Desea guardar el archivo actual antes de continuar?"
)
cancel = result is None
save_before = result is True
# Si el usuario canceló el diálogo, no continuar.
if cancel:
return False
# Si eligió guardar el archivo, guardar y continuar.
elif save_before:
self.save()
return True
# Si no hubo modificaciones, continuar sin guardar.
return True
def new(self) -> None:
if not self.can_continue():
return
# Eliminar el texto anterior.
self.text.delete("1.0", tk.END)
self.current_file = None
self.title("Bloc de notas")
def open(self) -> None:
filename = filedialog.askopenfilename(filetypes=self.filetypes)
if not filename or not self.can_continue():
return
# Eliminar el texto anterior e insertar el contenido
# del arhcivo seleccionado por el usuario.
self.text.delete("1.0", tk.END)
file = Path(filename)
self.text.insert("1.0", file.read_text("utf8"))
# Reiniciar el estado del texto cuando se abre un nuevo
# archivo.
self.text.edit_modified(False)
self.set_current_file(file)
def save_current_file(self) -> None:
if self.current_file is None:
return
self.current_file.write_text(self.text.get("1.0", tk.END), "utf8")
def save(self) -> None:
if self.current_file is None:
self.save_as()
return
self.save_current_file()
def save_as(self) -> None:
filename = filedialog.asksaveasfilename(
defaultextension=".txt",
filetypes=self.filetypes
)
# No hacer nada si el usuario canceló o cerró el
# diálogo.
if not filename:
return
self.set_current_file(Path(filename))
self.save_current_file()
notepad = Notepad()
notepad.mainloop()
Curso online 👨💻
¡Ya lanzamos el curso oficial de Recursos Python en Udemy!
Un curso moderno para aprender Python desde cero con programación orientada a objetos, SQL y tkinter en 2024.
Consultoría 💡
Ofrecemos servicios profesionales de desarrollo y capacitación en Python a personas y empresas. Consultanos por tu proyecto.
