Я пытаюсь создать приложение для отображения файлов PDF внутри него. И, может быть, это было бы не так сложно сделать, но у меня есть несколько шагов:
Я написал простой код, который покажет мою проблему.
from tkinter import *
from tkinter import ttk
import tkinter as tk
from io import BytesIO
from tkPDFViewer import tkPDFViewer as pdf
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4, landscape
from reportlab.lib.units import mm
main = tk.Tk()
main.title("PDF Viewer Main")
# Main window sizes
app_height = 350
app_width = 350
# Define of screen sizes
screen_width = main.winfo_screenwidth()
screen_height = main.winfo_screenheight()
# Define of left corner coordinates
x = (screen_width - app_width) / 2
y = ((screen_height - app_height)-50) / 2
# Applying defineded parameters to root.geometry
main.geometry(f'{app_width}x{app_height}+{int(x)}+{int(y)}')
main.resizable(False, False)
main.configure(background = "white")
def create_pdf():
pdf_reader = Toplevel(main)
pdf_reader.title("PDF Viewer")
# Main window sizes
app_height = 700
app_width = 900
# Define of screen sizes
screen_width = pdf_reader.winfo_screenwidth()
screen_height = pdf_reader.winfo_screenheight()
# Define of left corner coordinates
x = (screen_width - app_width) / 2
y = ((screen_height - app_height)-50) / 2
# Applying defineded parameters to root.geometry
pdf_reader.geometry(f'{app_width}x{app_height}+{int(x)}+{int(y)}')
pdf_reader.resizable(False, False)
pdf_reader.configure(background = "white")
buffer = BytesIO()
c = canvas.Canvas(buffer, pagesize=landscape(A4), bottomup=0)
c.drawString(400,300,"Sample PDF file")
c.save()
buffer.seek(0)
pdf_path = buffer.getvalue()
#print(pdf_path)
# creating object of ShowPdf from tkPDFViewer.
v1 = pdf.ShowPdf()
# Adding pdf location and width and height.
v2 = v1.pdf_view(pdf_reader, pdf_location = pdf_path, width = 50, height = 100, bar=True, load = "before")
# Placing Pdf in my gui.
v2.pack()
pdf_reader.mainloop()
create_btn = Button(main, text = "Create PDF file", command=create_pdf)
create_btn.pack(pady=135)
main.mainloop()
Но, может быть, мой выбор был неправильным, и «tkpdfviewer» не подходит для использования, потому что он не может отображать PDF-файлы из байтов? У меня есть следующая проблема:
Exception in thread Thread-1 (add_img):
Traceback (most recent call last):
File "C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\threading.py", line 1038, in _bootstrap_inner
self.run()
File "C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\threading.py", line 975, in run
self._target(*self._args, **self._kwargs)
File "C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\site-packages\tkPDFViewer\tkPDFViewer.py", line 43, in add_img
open_pdf = fitz.open(pdf_location)
^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\site-packages\fitz\fitz.py", line 3925, in __init__
raise TypeError(msg)
TypeError: bad filename
"tkpdfviewer" работает, но ничего не показывает.
Может ли кто-нибудь помочь мне решить эту проблему? Моя идея состоит в том, чтобы создать файл PDF и показать его без сохранения на компьютере.
@ acw1668 acw1668, так что бы вы могли мне посоветовать использовать только для отображения PDF-файлов из памяти с помощью BytesIO?
Я бы посоветовал вам скопировать файл tkPDFViewer.py
из модуля в каталог вашего проекта и удалить модуль. Затем исправьте проблему, отредактировав файл напрямую.
Согласно ответу @acw1668, я внес некоторые изменения в основную библиотеку «tkpdfviewer», и теперь она работает нормально!
Несколько изменений в коде:
Эта строка:
def pdf_view(self,master,width=1200,height=600,pdf_location = "",bar=True,load = "after"):
С помощью этой строки:
def pdf_view(self,master,width=1200,height=600,mem_area = "",bar=True,load = "after"):
В функции:
def add_img():
Я изменил эти строки кода:
precentage_dicide = 0
open_pdf = fitz.open(pdf_location)
for page in open_pdf:
pix = page.getPixmap()
pix1 = fitz.Pixmap(pix,0) if pix.alpha else pix
img = pix1.getImageData("ppm")
С этим:
precentage_dicide = 0
open_pdf = fitz.open("pdf", mem_area)
for page in open_pdf:
pix = page.get_pixmap()
pix1 = fitz.Pixmap(pix,0) if pix.alpha else pix
img = pix1.tobytes("ppm")
Я бы предложил заменить open_pdf = fitz.open(pdf_location)
на open_pdf = fitz.open(filename=pdf_location) if type(pdf_location) is str else fitz.open(stream=pdf_location)
. Тогда вы все равно можете передать имя файла через аргумент pdf_location
.
Вы не можете передать файловый объект в
pdf_location
опцию.pdf_view()
. Вам нужно изменитьtkPDFViewer
, чтобы удовлетворить его. ТакжеtkPDFViewer
больше не совместим с последней версиейPyMuPDF
.