Başlık: Python ve PyQt5 Kullanarak PDF Dosyalarını Bölme Aracı Geliştirme
Dün akşam discordda konuştuğum forumdan bir arkadaşımız pdf bölücü istemişti basit birşey yamıştım. Farklı bir arkadaşla konuşurken biraz geliştirmiştim. Şuanda ise en son halini paylaşıyorum. Kullanmak yada geliştirmek isteyenler için bütün açıklmalarını eksiksiz bir biçimde paylaştım.
<div style="position: relative; padding-bottom: 56.25%; height: 0;"><iframe id="js_video_iframe" src="https://jumpshare.com/embed/OwulHOeOp1YA8jI9a5Fj" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></iframe></div>
Giriş:
Bu makalede, Python programlama dili ve PyQt5 kütüphanesi kullanılarak PDF dosyalarını belirli parçalara bölen bir masaüstü uygulamasının nasıl geliştirildiğini inceleyeceğiz. Bu proje, PDF dosyalarını kullanıcıların belirlediği parça sayısına veya her parçanın içereceği sayfa sayısına göre bölen bir arayüz sunar. Kullanıcı, bir PDF dosyası seçtikten sonra bu dosyayı kaç parçaya böleceğine veya her parçanın kaç sayfa içereceğine karar verir ve bu işlemi başlatır. Bu makale boyunca, kodun tüm detaylarını, kullanılan kütüphaneleri ve bu projenin ne işe yaradığını açıklayacağız.
Kullanılan Kütüphaneler ve Kurulumları:
PyQt5: Kullanıcı arayüzünü oluşturmak için kullanılan popüler bir Python kütüphanesidir. PyQt5, butonlar, spinbox'lar, label'lar gibi çeşitli grafik bileşenlerini sağlar.
Kurulum:
pip install PyQt5
fitz (PyMuPDF): Bu kütüphane, PDF dosyalarıyla çalışmak ve sayfaları ayırmak, birleştirmek gibi işlemleri gerçekleştirmek için kullanılır.
Kurulum:
pip install PyMuPDF
sys, os ve time: Python’un standart kütüphanelerindendir. sys
, uygulamanın komut satırından başlatılması için kullanılır. os
, dosya ve dizinlerle ilgili işlemler yapmak için kullanılırken, time
ise işlem sürelerini hesaplamak için kullanılır.
Kodun İşleyişi:
Bu programda, kullanıcının seçtiği PDF dosyasını belirli parçalara bölmek için grafiksel bir arayüz tasarlanmıştır. Kullanıcı, PDF dosyasını seçtikten sonra iki seçenek sunulur:
- PDF dosyasını kaç parçaya bölmek istediği.
- Her parçanın kaç sayfa içereceği.
Bu iki seçenek, QRadioButton
ve QSpinBox
bileşenleri ile kullanıcıya sunulmaktadır. Kullanıcı uygun seçeneği işaretleyip ayarlarını yaptıktan sonra Kaydet butonuna tıklayarak bölme işlemini başlatır.
Kodun Detaylı Açıklaması:
PDF Seçimi:
select_pdf
fonksiyonu, kullanıcıdan PDF dosyasını seçmesini sağlar. Seçilen dosyanın yolu bir status bar üzerinde gösterilir ve toplam sayfa sayısı load_pdf_info
fonksiyonu ile belirlenir.
UI Güncellemesi:
update_ui
fonksiyonu, kullanıcı hangi seçeneği işaretlediğine göre uygun SpinBox
bileşenini etkinleştirir. Bu, kullanıcı deneyimini geliştiren önemli bir adımdır.
PDF Dosyasının Bölünmesi:
split_pdf_by_parts_or_pages
fonksiyonu, kullanıcıdan alınan bilgiye göre PDF dosyasını parçalar. Eğer kullanıcı dosyayı kaç parçaya böleceğini seçtiyse (radio_parts
), toplam sayfa sayısı parça sayısına bölünerek her parçanın kaç sayfa içereceği belirlenir. Eğer kullanıcı her parçanın kaç sayfa içereceğini belirlediyse (radio_pages
), bu durumda bu sayı kadar sayfa içeren parçalar oluşturulur.
Bölme İşleminin Durumu:
Bölme işlemi sırasında, kullanıcının bilgilendirilmesi amacıyla bir progress bar kullanılır ve status bar'da her bir parçanın kaydedilme durumu gösterilir. Bu sayede kullanıcı, işlemin ne kadarının tamamlandığını anlık olarak görebilir.
Hata Yönetimi:
split_pdf_by_parts_or_pages
fonksiyonunda bir hata oluşması durumunda, bu hata except
bloğunda yakalanır ve kullanıcıya bir hata mesajı gösterilir. Bu, uygulamanın beklenmedik durumlarda çökmesini engelleyen ve kullanıcıya bilgi veren bir yaklaşımdır.
Sonuç:
Bu uygulama, kullanıcıların büyük PDF dosyalarını daha küçük parçalara bölerek yönetmelerini kolaylaştıran etkili bir araçtır. PyQt5 ile sağlanan kullanıcı dostu grafik arayüzü, işlemleri hızlı ve sorunsuz bir şekilde yapmayı mümkün kılar. fitz
kütüphanesi (PyMuPDF), PDF dosyalarını işlemek ve her bir parçayı kaydetmek için güçlü bir çözüm sunar.
Kodu çalıştırmak ve uygulamayı kullanmak için yukarıda belirtilen bağımlılıkları yükledikten sonra, Python ortamında aşağıdaki komut çalıştırılarak uygulama başlatılabilir:
python pdf_splitter.py
Bu komut, kullanıcıya PDF dosyalarını bölme işlemlerini gerçekleştirebileceği bir arayüz sunacaktır.
Kodun Tamamı:
import sys
import os
import time
import fitz # PyMuPDF
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QFileDialog, QProgressBar, QLabel, QSpinBox, QVBoxLayout, QWidget, QStatusBar, QRadioButton, QButtonGroup, QGroupBox, QHBoxLayout
from PyQt5.QtCore import Qt
class PDFSplitterApp(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle('PDF Splitter')
self.setGeometry(100, 100, 400, 500)
# Ana widget ve layout
widget = QWidget()
layout = QVBoxLayout()
# PDF Seç Butonu
self.select_button = QPushButton('PDF Seç', self)
self.select_button.clicked.connect(self.select_pdf)
layout.addWidget(self.select_button)
# Seçilen PDF'in toplam sayfa sayısını gösteren Label
self.page_count_label = QLabel('Toplam Sayfa: 0', self)
layout.addWidget(self.page_count_label)
# RadioButton Gruplaması
self.button_group = QButtonGroup()
# Kaç Parta Bölünecek Paneli
self.part_group = QGroupBox("Kaç Parta Bölünecek")
part_layout = QVBoxLayout()
self.radio_parts = QRadioButton("Kaç Parta Bölünecek", self)
self.radio_parts.toggled.connect(self.update_ui)
part_layout.addWidget(self.radio_parts)
self.split_spin = QSpinBox(self)
self.split_spin.setMinimum(1)
self.split_spin.setMaximum(100) # Max 100 parçaya bölünebilir
part_layout.addWidget(self.split_spin)
self.part_group.setLayout(part_layout)
layout.addWidget(self.part_group)
# ButtonGroup'a ekle
self.button_group.addButton(self.radio_parts)
# Her Parça Kaç Sayfa İçerecek Paneli
self.page_group = QGroupBox("Her Parça Kaç Sayfa İçerecek")
page_layout = QVBoxLayout()
self.radio_pages = QRadioButton("Her Parça Kaç Sayfa İçerecek", self)
self.radio_pages.toggled.connect(self.update_ui)
page_layout.addWidget(self.radio_pages)
self.pages_spin = QSpinBox(self)
self.pages_spin.setMinimum(1)
page_layout.addWidget(self.pages_spin)
self.page_group.setLayout(page_layout)
layout.addWidget(self.page_group)
# ButtonGroup'a ekle
self.button_group.addButton(self.radio_pages)
# Kaydet Butonu
self.save_button = QPushButton('Kaydet', self)
self.save_button.clicked.connect(self.split_pdf_by_parts_or_pages)
layout.addWidget(self.save_button)
# Progress Bar
self.progress_bar = QProgressBar(self)
layout.addWidget(self.progress_bar)
# Status Bar
self.status_bar = QStatusBar(self)
self.setStatusBar(self.status_bar)
widget.setLayout(layout)
self.setCentralWidget(widget)
# PDF dosyası yolu
self.pdf_path = None
self.total_pages = 0
# Varsayılan ayar
self.radio_parts.setChecked(True)
self.update_ui()
def select_pdf(self):
options = QFileDialog.Options()
file_name, _ = QFileDialog.getOpenFileName(self, "PDF Dosyası Seç", "", "PDF Files (*.pdf);;All Files (*)", options=options)
if file_name:
self.pdf_path = file_name
self.status_bar.showMessage(f'Seçilen PDF: {os.path.basename(self.pdf_path)}')
self.load_pdf_info()
def load_pdf_info(self):
if self.pdf_path:
# PDF dosyasını aç ve toplam sayfa sayısını al
pdf_document = fitz.open(self.pdf_path)
self.total_pages = pdf_document.page_count
self.page_count_label.setText(f'Toplam Sayfa: {self.total_pages}')
self.pages_spin.setMaximum(self.total_pages)
pdf_document.close()
def update_ui(self):
if self.radio_parts.isChecked():
self.split_spin.setEnabled(True)
self.pages_spin.setEnabled(False)
elif self.radio_pages.isChecked():
self.split_spin.setEnabled(False)
self.pages_spin.setEnabled(True)
def split_pdf_by_parts_or_pages(self):
if not self.pdf_path:
self.status_bar.showMessage('Lütfen önce bir PDF dosyası seçin.')
return
# Seçilen PDF dosyasını aç
pdf_document = fitz.open(self.pdf_path)
total_pages = pdf_document.page_count
start_time = time.time()
output_dir = os.path.join(os.path.dirname(self.pdf_path), 'split_parts')
os.makedirs(output_dir, exist_ok=True)
self.progress_bar.setValue(0)
try:
if self.radio_parts.isChecked():
# Parça sayısına göre bölme
split_count = self.split_spin.value()
pages_per_part = total_pages // split_count
remaining_pages = total_pages % split_count
part = 1
for i in range(0, total_pages, pages_per_part):
output_pdf = fitz.open()
for j in range(i, min(i + pages_per_part, total_pages)):
output_pdf.insert_pdf(pdf_document, from_page=j, to_page=j)
if part == split_count and remaining_pages != 0:
for k in range(total_pages - remaining_pages, total_pages):
output_pdf.insert_pdf(pdf_document, from_page=k, to_page=k)
output_path = os.path.join(output_dir, f'part_{part}.pdf')
output_pdf.save(output_path)
output_pdf.close()
progress = int((part / split_count) * 100)
self.progress_bar.setValue(progress)
self.status_bar.showMessage(f'Parça {part} kaydedildi: {output_path}')
part += 1
elif self.radio_pages.isChecked():
# Sayfa sayısına göre bölme
split_by_pages = self.pages_spin.value()
part = 1
for i in range(0, total_pages, split_by_pages):
output_pdf = fitz.open()
for j in range(i, min(i + split_by_pages, total_pages)):
output_pdf.insert_pdf(pdf_document, from_page=j, to_page=j)
output_path = os.path.join(output_dir, f'part_{part}.pdf')
output_pdf.save(output_path)
output_pdf.close()
progress = int((part / (total_pages / split_by_pages)) * 100)
self.progress_bar.setValue(progress)
self.status_bar.showMessage(f'Parça {part} kaydedildi: {output_path}')
part += 1
self.status_bar.showMessage(f'İşlem tamamlandı. Toplam geçen süre: {time.time() - start_time:.2f} saniye')
except Exception as e:
self.status_bar.showMessage(f'Hata: {str(e)}')
finally:
pdf_document.close()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = PDFSplitterApp()
ex.show()
sys.exit(app.exec_())