Sunday, May 24, 2026

Python GUI to delete (extract) pages from PDF

from tkinter import *

from tkinter import filedialog, messagebox

from PIL import Image, ImageTk

import fitz


root = Tk()

root.title("PDF Page Viewer")

root.geometry("900x700")


pdf_doc = None

pdf_path = ""

current_page = 0

deleted_pages = set()


frame = Frame(root)

frame.pack(fill=BOTH, expand=True)


canvas = Canvas(frame, bg="gray")

canvas.pack(fill=BOTH, expand=True)


button_frame = Frame(root)

button_frame.pack(fill=X)


img_tk = None


def open_pdf():

  global pdf_doc, pdf_path, current_page, deleted_pages


  path = filedialog.askopenfilename(filetypes=[("PDF Files", "*.pdf")])


  if not path:

    return


  pdf_path = path

  pdf_doc = fitz.open(path)

  current_page = 0

  deleted_pages = set()


  show_page()


def valid_pages():

  return [i for i in range(len(pdf_doc)) if i not in deleted_pages]


def show_page():

  global img_tk


  if pdf_doc is None:

    return


  pages = valid_pages()


  if not pages:

    canvas.delete("all")

    messagebox.showinfo("Info", "No pages remaining")

    return


  page_number = pages[current_page]


  page = pdf_doc.load_page(page_number)


  pix = page.get_pixmap(matrix=fitz.Matrix(2, 2))


  img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)


  canvas_width = canvas.winfo_width()

  canvas_height = canvas.winfo_height()


  if canvas_width > 1 and canvas_height > 1:

    img.thumbnail((canvas_width, canvas_height))


  img_tk = ImageTk.PhotoImage(img)


  canvas.delete("all")

  canvas.create_image(

    canvas.winfo_width() // 2,

    canvas.winfo_height() // 2,

    image=img_tk,

    anchor=CENTER

  )


  root.title(f"PDF Viewer - Page {current_page + 1} of {len(pages)}")


def next_page():

  global current_page


  if pdf_doc is None:

    return


  pages = valid_pages()


  if current_page < len(pages) - 1:

    current_page += 1

    show_page()


def delete_page():

  global current_page


  if pdf_doc is None:

    return


  pages = valid_pages()


  if not pages:

    return


  page_to_delete = pages[current_page]


  deleted_pages.add(page_to_delete)


  remaining = valid_pages()


  if current_page >= len(remaining) and current_page > 0:

    current_page -= 1


  show_page()


def save_pdf():

  if pdf_doc is None:

    return


  pages = valid_pages()


  if not pages:

    messagebox.showerror("Error", "No pages to save")

    return


  save_path = filedialog.asksaveasfilename(

    defaultextension=".pdf",

    filetypes=[("PDF Files", "*.pdf")]

  )


  if not save_path:

    return


  new_pdf = fitz.open()


  for p in pages:

    new_pdf.insert_pdf(pdf_doc, from_page=p, to_page=p)


  new_pdf.save(save_path)

  new_pdf.close()


  messagebox.showinfo("Saved", "PDF saved successfully")


Button(button_frame, text="OPEN PDF", command=open_pdf).pack(side=LEFT, padx=10, pady=10)

Button(button_frame, text="NEXT", command=next_page).pack(side=LEFT, padx=10, pady=10)

Button(button_frame, text="DELETE", command=delete_page).pack(side=LEFT, padx=10, pady=10)

Button(button_frame, text="SAVE", command=save_pdf).pack(side=LEFT, padx=10, pady=10)


canvas.bind("<Configure>", lambda e: show_page())


root.mainloop()


No comments:

Post a Comment