PDF Pythonツール ドラッグアンドドロップ(単一ファイル) ファイル指定 文字列挿入

PythonでPDFビュアーを作成する!その2 ドラッグ&ドロップとテキスト挿入機能の追加

概要

このブログでは、Pythonといくつかのライブラリを使用して、テキスト挿入機能付きPDFビュアーを作成する方法を詳細に解説します。このPDFビュアーには、ドラッグアンドドロップ機能、ページナビゲーション、テキスト挿入機能、マウスカーソルの座標表示機能など、さまざまな便利な機能を搭載しています。

下記は前回作成したpdfビュアーの記事になります。

使用例

このPDFビュアーは、教育資料や業務報告書など、さまざまなPDFファイルを視覚的にナビゲートするためのツールとして利用可能です。ユーザーはファイルをアプリケーションにドラッグアンドドロップするだけでなく、ファイルダイアログを使用してPDFを開くことができ、ページごとに詳細なビューを得ることができます。また、マウスカーソルの座標をリアルタイムで確認し、特定の位置にテキストを挿入することができます。

必要なPythonライブラリとインストール方法

このプロジェクトには以下のライブラリが必要です:

  • tkinter: Pythonの標準GUIツールキット。
  • PyMuPDF (別名 fitz): PDFファイルを操作するためのライブラリ。
  • tkinterdnd2: ドラッグアンドドロップ機能を実装するためのライブラリ。

これらのライブラリのインストール方法は以下の通りです:

pip install pymupdf
pip install tkinterdnd2

使用手順

  1. 上記のライブラリをインストールします。
  2. 提供されたコードをメモ帳などに丸々コピーしてPythonファイル(例:pdf_viewer.py)に保存します。
  3. 保存したPythonファイルを実行します。
  4. PDFファイルをウィンドウにドラッグアンドドロップするか、「Open File」ボタンをクリックしてファイルを選択し、PDFを表示します。
  5. 画面下部に表示されるナビゲーションボタンを使用して、ページ間を移動します。
  6. 「Add Text」ボタンをクリックしてテキストを入力し、挿入する位置を指定します。
  7. 必要に応じて、「Save PDF」ボタンをクリックして編集済みのPDFを保存します。

注意点

  • PDFファイルのパスに特殊文字が含まれている場合、エラーが発生する可能性があります。これを避けるために、ファイルパスを適切に処理する必要があります。
  • 一部のPDFファイルでは、保護されているために読み込みができないことがあります。これらのファイルは事前に保護解除が必要です。
  • 文字の位置はページの高さを基準に計算されるため、Y座標を入力する際には注意が必要です。

プログラム

下記のコードをメモ帳などに丸々コピーしてPythonファイル(例:pdf_viewer.py)にしてください。

import tkinter as tk
from tkinter import filedialog, simpledialog
from tkinterdnd2 import DND_FILES, TkinterDnD
import fitz # PyMuPDF

class PDFViewer:
def __init__(self, root):
self.root = root
self.doc = None
self.current_page = 0
self.total_pages = 0
self.text = None
self.text_size = 11
self.text_x = 0
self.text_y = 0
self.page_height = 0 # ページの高さを保存する変数

self.label = tk.Label(root)
self.label.pack(fill=tk.BOTH, expand=True)

btn_frame = tk.Frame(root)
btn_frame.pack(fill=tk.X)
self.prev_btn = tk.Button(btn_frame, text="<< Previous", command=self.prev_page)
self.prev_btn.pack(side=tk.LEFT)
self.next_btn = tk.Button(btn_frame, text="Next >>", command=self.next_page)
self.next_btn.pack(side=tk.RIGHT)
open_btn = tk.Button(btn_frame, text="Open File", command=self.open_file_dialog)
open_btn.pack(side=tk.LEFT)
add_text_btn = tk.Button(btn_frame, text="Add Text", command=self.add_text_dialog)
add_text_btn.pack(side=tk.LEFT)
save_btn = tk.Button(btn_frame, text="Save PDF", command=self.save_pdf)
save_btn.pack(side=tk.RIGHT)

# ファイルパス表示用ラベル
self.file_path_label = tk.Label(root, text="No file selected")
self.file_path_label.pack(side=tk.TOP)

# 座標表示用ラベル
self.coord_label = tk.Label(root, text="X: 0, Y: 0")
self.coord_label.pack(side=tk.BOTTOM)

self.label.bind('<Motion>', self.mouse_move) # マウス移動イベントをバインド

root.drop_target_register(DND_FILES)
root.dnd_bind('<<Drop>>', self.drop)

def open_file_dialog(self):
file_path = filedialog.askopenfilename(filetypes=[("PDF files", "*.pdf")])
if file_path:
self.file_path_label.config(text=f"Selected file: {file_path}")
self.open_pdf(file_path)

def open_pdf(self, path):
self.doc = fitz.open(path)
self.total_pages = len(self.doc)
self.current_page = 0
self.show_page(self.current_page)

def show_page(self, page_num):
page = self.doc.load_page(page_num)
self.page_height = page.rect.height # ページの高さを取得
pix = page.get_pixmap()
if self.text:
self.add_text_to_page(page)
pix = page.get_pixmap() # Update the pixmap after adding text
img = tk.PhotoImage(data=pix.tobytes("ppm"))
self.label.config(image=img)
self.label.image = img
# Adjust window size
self.root.geometry(f"{pix.width}x{pix.height + 100}")

def add_text_dialog(self):
self.text = simpledialog.askstring("Input", "Enter the text to add:", parent=self.root)
self.text_size = simpledialog.askinteger("Input", "Enter font size:", parent=self.root, initialvalue=11)
self.text_x = simpledialog.askinteger("Input", "Enter X coordinate:", parent=self.root, initialvalue=0)
self.text_y = simpledialog.askinteger("Input", "Enter Y coordinate:", parent=self.root, initialvalue=0)
self.text_y = self.page_height - self.text_y # Y座標を反転
self.show_page(self.current_page) # Update the display with the new text

def add_text_to_page(self, page):
if not self.text:
return
# Y座標を反転してテキストを追加
page.insert_text((self.text_x, self.text_y), text=self.text, fontsize=self.text_size, color=(1, 0, 0))

def prev_page(self):
if self.current_page > 0:
self.current_page -= 1
self.show_page(self.current_page)

def next_page(self):
if self.current_page < self.total_pages - 1:
self.current_page += 1
self.show_page(self.current_page)

def mouse_move(self, event):
# ラベルに座標を表示
self.coord_label.config(text=f"X: {event.x}, Y: {self.page_height - event.y}")

def save_pdf(self):
file_path = filedialog.asksaveasfilename(defaultextension=".pdf", filetypes=[("PDF files", "*.pdf")])
if file_path:
self.doc.save(file_path)

def drop(self, event):
file_path = event.data
file_path = file_path.strip('\'"{}')
self.file_path_label.config(text=f"Selected file: {file_path}")
self.open_pdf(file_path)

root = TkinterDnD.Tk()
root.title('PDF Viewer')
root.geometry('800x600')
app = PDFViewer(root)
root.mainloop()

あるいは、下のテキストファイルをダウンロードし、「.txt」を「.py」に変えることでそのまま使えます。

まとめ

このブログでは、Pythonを使用して機能豊富なPDFビュアーを開発する方法を紹介しました。GUI操作により、ユーザーフレンドリーで直感的なPDF管理ツールを簡単に作成できます。このツールは、教育、ビジネス、研究など多岐にわたる分野での文書管理とレビューに役立つでしょう。

-PDF, Pythonツール, ドラッグアンドドロップ(単一ファイル), ファイル指定, 文字列挿入