edit_redo、edit_undo Python

问题描述 投票:0回答:1

英语:我需要对右侧框架中编辑文本的文本使用撤消和重做。我尝试了多种方法但没能成功,它只是没有做任何事情,没有错误,什么也没有。 我会留下代码,以便您可以帮助我

西班牙语:necesito utilizar el undo y redo para el texto que está en el frame derecho, donde se edita el texto。他 probado de multiples formas y no he podido, simplemente no hace nada, no hay errores, no hay nada。 dejare el código para que puedan hacharme una mano

import tkinter as tk
from tkinter import messagebox, filedialog, Scrollbar, TOP, X, RIGHT, Y, BOTH, LEFT, Text
import sqlite3
from PIL import Image, ImageTk
from email.message import EmailMessage
import smtplib
from docx import Document
import os
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import inch
from reportlab.platypus import SimpleDocTemplate, Paragraph
from docx.shared import Pt

class MasterPanel:
    def __init__(self):
        self.ventana = tk.Tk()
        self.ventana.title('Master panel')

        # Configuración de la ventana
        w, h = self.ventana.winfo_screenwidth(), self.ventana.winfo_screenheight()
        w -= 10
        h -= 55
        self.ventana.geometry("%dx%d+0+0" % (w, h))
        self.ventana.config(bg='#e8cebd')
        self.ventana.resizable(width=0, height=0)

        # Crear el frame principal
        main_frame = tk.Frame(self.ventana)
        main_frame.pack(fill='both', expand=True)

        # Frame izquierdo para el menú y la lista de documentos
        self.frame_izquierdo = tk.Frame(main_frame, bg='white', width=200)
        self.frame_izquierdo.pack(side='left', fill='both', expand=False)

        # Frame derecho para mostrar y editar el documento
        self.frame_derecho = tk.Frame(main_frame, bg='lightgrey')
        self.frame_derecho.pack(side='right', fill='both', expand=True)

        # Barra de herramientas
        self.crear_barra_herramientas()

        # Obtener documentos desde la base de datos
        documentos = self.consultar_documentos()

        self.undo_stack = []  # Inicialización de la pila de deshacer
        self.redo_stack = []  # Inicialización de la pila de rehacer

        # Mostrar los documentos en el frame izquierdo
        label_menu = tk.Label(self.frame_izquierdo, text='Documentos', font=('Arial', 12), bg='white')
        label_menu.pack(pady=20)

        self.listbox_documentos = tk.Listbox(self.frame_izquierdo, width=30, height=10)
        for documento in documentos:
            self.listbox_documentos.insert(tk.END, documento[0])  # Mostrar solo el nombre del documento
        self.listbox_documentos.pack(padx=20, pady=10, fill='both', expand=True)
        self.listbox_documentos.bind("<<ListboxSelect>>", self.mostrar_documento_seleccionado)

        


    def show_context_menu(self, event):
        self.context_menu.tk_popup(event.x_root, event.y_root)

    def apply_tag(self, tag_name, tag_property):
        try:
            # Obtener el texto seleccionado
            start_index = self.text_documento.index("sel.first")
            end_index = self.text_documento.index("sel.last")
            self.text_documento.tag_add(tag_name, start_index, end_index)
            self.text_documento.tag_config(tag_name, font=(None, 12, tag_property))
        except tk.TclError:
            messagebox.showinfo("Error", "Por favor, selecciona texto primero.")

    def toggle_bold(self):
        self.remove_formatting()
        self.apply_tag("bold", "bold")

    def toggle_italic(self):
        self.remove_formatting()
        self.apply_tag("italic", "italic")

    def toggle_underline(self):
        self.remove_formatting()
        self.apply_tag("underline", "underline")

    def remove_formatting(self):
        self.text_documento.tag_remove("bold", "sel.first", "sel.last")
        self.text_documento.tag_remove("italic", "sel.first", "sel.last")
        self.text_documento.tag_remove("underline", "sel.first", "sel.last")


    
    def crear_barra_herramientas(self):
        # Barra de herramientas
        barra_menus = tk.Menu(self.ventana)
        self.ventana.config(menu=barra_menus)
        self.barra_menus = barra_menus

        # Menú Archivo
        menu_archivo = tk.Menu(barra_menus, tearoff=0)

        menu_archivo.add_command(
            label="Guardar",accelerator="Ctrl+S", compound="left",command=self.guardar_documento)
        self.ventana.bind_all("<Control-s>", self.guardar_documento)
        menu_archivo.add_separator()
        
        menu_archivo.add_command(
            label="Subir a Base de Datos",accelerator="Ctrl+O",compound="left",command=self.subir_documento)
        self.ventana.bind_all("<Control-o>", self.subir_documento)
        barra_menus.add_cascade(menu=menu_archivo, label="Archivo")

        # Crear el nuevo menú "Edición" y añadir opciones dentro
        menu_edicion = tk.Menu(self.ventana, tearoff=0)
        menu_edicion.add_command(label="Deshacer", command=self.undo_action, accelerator="Ctrl+Z")
        self.ventana.bind_all("<Control-z>", self.undo_action)  # Asignar atajo de teclado a Deshacer
        menu_edicion.add_command(label="Rehacer", command=self.redo_action, accelerator="Ctrl+Y")
        self.ventana.bind_all("<Control-y>", self.redo_action)  # Asignar atajo de teclado a Rehacer

        # Agregar el nuevo menú "Edición" al menú principal
        self.barra_menus.add_cascade(menu=menu_edicion, label="Edición")




    def guardar_documento(self, event=None):
        # Obtener el contenido actual del documento
        contenido_actual = self.text_documento.get('1.0', tk.END)

        # Ventana para seleccionar la ruta de guardado
        file_path = filedialog.asksaveasfilename(defaultextension=".docx", filetypes=[("Word Document", "*.docx"),
                                                                                     ("PDF", "*.pdf")])

        if file_path.endswith('.docx'):
            doc = Document()
            # Configurar el estilo del documento DOCX
            style = doc.styles['Normal']
            font = style.font
            font.name = 'Times New Roman'
            font.size = Pt(12)

            # Añadir el contenido al documento con formato
            for line in contenido_actual.split('\n'):
                p = doc.add_paragraph(line.strip())
                p.alignment = 3  # 3 representa el justificado

                # Guardar como archivo DOCX
                doc.save(file_path)

        elif file_path.endswith('.pdf'):
            doc = SimpleDocTemplate(file_path, pagesize=letter)

            # Configurar el estilo del documento PDF
            style = getSampleStyleSheet()["Normal"]
            style.fontName = 'Times-Roman'
            style.fontSize = 12

            # Añadir el contenido al documento con formato
            content = []
            for line in contenido_actual.split('\n'):
                content.append(Paragraph(line.strip(), style))

            # Crear el PDF con contenido justificado
            doc.build(content)

            # Enviar correo electrónico
        if self.enviar_correo(file_path):
            messagebox.showinfo("Correo Enviado",
                                "El documento ha sido guardado en la dirección "
                                "establecida.")


    def subir_documento(self, event=None):
        os.system('python BD.py')
        # Recargar los documentos desde la base de datos
        documentos = self.consultar_documentos()
        # Limpiar la lista actual de documentos
        self.listbox_documentos.delete(0, tk.END)
        # Agregar los nuevos documentos a la lista
        for documento in documentos:
            self.listbox_documentos.insert(tk.END, documento[0])

    def consultar_documentos(self):
        # Conectar a la base de datos
        conexion = sqlite3.connect('documentos.db')
        cursor = conexion.cursor()

        # Ejecutar la consulta para obtener los nombres de los documentos
        cursor.execute("SELECT nombre_documento FROM documentos")
        documentos = cursor.fetchall()

        # Cerrar la conexión a la base de datos
        conexion.close()

        return documentos

    def mostrar_documento_seleccionado(self, event):
        seleccion = self.listbox_documentos.curselection()
        if seleccion:
            nombre_documento = self.listbox_documentos.get(seleccion)
            contenido_documento = self.obtener_contenido_documento(nombre_documento)
            self.mostrar_docx_en_frame(contenido_documento)

    def obtener_contenido_documento(self, nombre_documento):
        # Conectar a la base de datos
        conexion = sqlite3.connect('documentos.db')
        cursor = conexion.cursor()

        # Ejecutar la consulta para obtener el contenido del documento seleccionado
        cursor.execute("SELECT contenido FROM documentos WHERE nombre_documento = ?", (nombre_documento,))
        contenido = cursor.fetchone()[0]

        # Cerrar la conexión a la base de datos
        conexion.close()

        return contenido

    def mostrar_docx_en_frame(self, contenido_docx):
        # Limpiar el frame derecho antes de mostrar el nuevo documento
        for widget in self.frame_derecho.winfo_children():
            widget.destroy()

        # Crear un widget Text para mostrar y editar el documento .docx
        self.text_documento = Text(self.frame_derecho, wrap='word')
        self.text_documento.insert('1.0', contenido_docx)
        self.text_documento.pack(fill=BOTH, expand=True)

        # Configurar scrollbar para el texto del documento
        scrollbar = Scrollbar(self.text_documento)
        scrollbar.pack(side=RIGHT, fill=Y)
        scrollbar.config(command=self.text_documento.yview)
        self.text_documento.config(yscrollcommand=scrollbar.set)

        # Crear el menú contextual para el widget Text
        self.context_menu = tk.Menu(self.ventana, tearoff=0)
        self.context_menu.add_command(label="Negrita", command=self.toggle_bold)
        self.context_menu.add_command(label="Cursiva", command=self.toggle_italic)
        self.context_menu.add_command(label="Subrayado", command=self.toggle_underline)
        self.context_menu.add_command(label="Quitar todo", command=self.remove_formatting)

        # Vincular el menú contextual al evento del botón derecho del ratón
        self.text_documento.bind("<Button-3>", self.show_context_menu)
        
        self.text_documento.bind("<Control-z>", self.undo_action)
        self.text_documento.bind("<Control-y>", self.redo_action)

    def undo_action(self, event=None):
        try:
            self.text_documento.edit_undo()
        except tk.TclError:
            messagebox.showinfo("No se puede deshacer", "No hay acciones para deshacer.")

    def redo_action(self, event=None):
        try:
            self.text_documento.edit_redo()
        except tk.TclError:
            messagebox.showinfo("No se puede rehacer", "No hay acciones para rehacer.")
            
if __name__ == "__main__":
    app = MasterPanel()
    app.ventana.mainloop()

python user-interface tkinter python-docx
1个回答
0
投票

我觉得错误可能出在以下部分之一:

# Crear el nuevo menú "Edición" y añadir opciones dentro
    menu_edicion = tk.Menu(self.ventana, tearoff=0)
    menu_edicion.add_command(label="Deshacer", command=self.undo_action, accelerator="Ctrl+Z")
    self.ventana.bind_all("<Control-z>", self.undo_action)  # Asignar atajo de teclado a Deshacer
    menu_edicion.add_command(label="Rehacer", command=self.redo_action, accelerator="Ctrl+Y")
    self.ventana.bind_all("<Control-y>", self.redo_action)  # Asignar atajo de teclado a Rehacer

    # Agregar el nuevo menú "Edición" al menú principal
    self.barra_menus.add_cascade(menu=menu_edicion, label="Edición")

def undo_action(self, event=None):
    try:
        self.text_documento.edit_undo()
    except tk.TclError:
        messagebox.showinfo("No se puede deshacer", "No hay acciones para deshacer.")

 def redo_action(self, event=None):
    try:
        self.text_documento.edit_redo()
    except tk.TclError:
        messagebox.showinfo("No se puede rehacer", "No hay acciones para rehacer.")

 def mostrar_docx_en_frame:
     self.text_documento.bind("<Control-z>", self.undo_action)
    self.text_documento.bind("<Control-y>", self.redo_action)
© www.soinside.com 2019 - 2024. All rights reserved.