반응형
import sys
import os

from PyPDF2.pdf import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *


class MainWidget(QWidget):
    def __init__(self):
        super().__init__()
        manual_label = [QLabel("<b>PDF Application"), QLabel("Created by JS")]

        for i in range(0, 2):
            manual_label[i].setStyleSheet("Color : gray")
            manual_label[i].setFont(QFont("", 40 - (12 * i)))

        hbox = [QHBoxLayout(), QHBoxLayout()]
        for i in range(0, 2):
            hbox[i].addStretch(1)
            hbox[i].addWidget(manual_label[i])
            hbox[i].addStretch(1)

        vbox = QVBoxLayout()
        vbox.addStretch(1)
        vbox.addLayout(hbox[0])
        vbox.addLayout(hbox[1])
        vbox.addStretch(1)

        self.setLayout(vbox)


class ListboxWidget(QListWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setAcceptDrops(True)

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls:
            event.accept()
        else:
            event.ignore()

    def dragMoveEvent(self, event):
        if event.mimeData().hasUrls():
            event.setDropAction(Qt.CopyAction)
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        if event.mimeData().hasUrls():
            event.setDropAction(Qt.CopyAction)
            event.accept()

            links = []

            for i in event.mimeData().urls():
                if str(i).find(".pdf") > 0:
                    if i.isLocalFile():
                        links.append(str(i.toLocalFile()))
                    else:
                        links.append(str(i.toString()))
            self.addItems(links)
        else:
            event.ignore()


class PDFMerge(QWidget):
    def __init__(self):
        super().__init__()
        self.pushButton = QPushButton(self)
        self.pushButton.setGeometry(QRect(20, 440, 451, 31))
        self.pushButton.setText("합치기")

        self.groupBox = QGroupBox(self)
        self.groupBox.setGeometry(QRect(20, 20, 451, 410))
        self.groupBox.setFlat(False)
        self.groupBox.setCheckable(False)
        self.groupBox.setTitle("<PDF 리스트>")

        self.listWidget = ListboxWidget(self.groupBox)
        self.listWidget.setGeometry(QRect(20, 30, 411, 250))

        self.pushButton_4 = QPushButton(self.groupBox)
        self.pushButton_4.setGeometry(QRect(20, 310, 93, 28))
        self.pushButton_4.setText("위 이동")

        self.pushButton_5 = QPushButton(self.groupBox)
        self.pushButton_5.setGeometry(QRect(20, 350, 93, 28))
        self.pushButton_5.setText("아래 이동")

        self.pushButton_6 = QPushButton(self.groupBox)
        self.pushButton_6.setGeometry(QRect(180, 310, 93, 71))
        self.pushButton_6.setText("추 가")

        self.pushButton_7 = QPushButton(self.groupBox)
        self.pushButton_7.setGeometry(QRect(340, 310, 93, 71))
        self.pushButton_7.setText("제 거")

        self.pushButton_6.clicked.connect(self.add_PDF)
        self.pushButton_7.clicked.connect(self.del_PDF)
        self.pushButton_4.clicked.connect(self.up_PDF)
        self.pushButton_5.clicked.connect(self.down_PDF)
        self.pushButton.clicked.connect(self.merge_PDF)

    def add_PDF(self):
        fname = QFileDialog.getOpenFileName(self, "open file", "", "PDF File(*.pdf)")
        self.listWidget.addItem(QListWidgetItem(fname[0]))

    def set_PDF(self):
        dirname = QFileDialog.getExistingDirectory(None)
        self.listWidget_2.clear()
        self.listWidget_2.addItem(QListWidgetItem(dirname))

    def del_PDF(self):
        self.listWidget.takeItem(self.listWidget.currentRow())

    def up_PDF(self):
        row = self.listWidget.currentRow()
        if row > 0:
            item = self.listWidget.takeItem(row)
            self.listWidget.insertItem(row - 1, item)
            self.listWidget.setCurrentRow(row - 1)

    def down_PDF(self):
        row = self.listWidget.currentRow()
        if row < self.listWidget.count() - 1:
            item = self.listWidget.takeItem(row)
            self.listWidget.insertItem(row + 1, item)
            self.listWidget.setCurrentRow(row + 1)

    def merge_PDF(self):
        count = self.listWidget.count()

        if count == 0:
            QMessageBox.information(self, '경고', "저장할 파일이 없습니다.", QMessageBox.Yes)

        else:
            down_path, _ = QFileDialog.getSaveFileName(self, "Open", "", "PDF(*.pdf)")

            if down_path:
                output = PdfFileWriter()
                for x in range(0, count):
                    src = self.listWidget.item(x)

                    inputs = PdfFileReader(open(src.text(), "rb"))
                    for j in range(inputs.getNumPages()):
                        output.addPage(inputs.getPage(j))
                dest = down_path

                with open(dest, "wb") as outstream:
                    output.write(outstream)


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        # menu bar widget 모음
        menu = self.menuBar()
        menu_pdf = menu.addMenu('    PDF   ')

        self.pdf_merge = QAction('PDF 합치기', self)
        menu_pdf.addAction(self.pdf_merge)  # menu bar 에 lpf 를 붙임
        self.pdf_merge.triggered.connect(lambda x: self.applyfunc('merge'))  # 로우패스필터를 누르면 applyDock 연결

        self.widget = MainWidget()
        self.setCentralWidget(self.widget)

        self.setEnabled(True)
        self.resize(500, 500)
        self.setWindowTitle("PDF Application")  # Program Title
        self.setFixedSize(500, 550)

        self.show()

    def applyfunc(self, function):
        if function == "merge":
            merge_widget = PDFMerge()
            self.setCentralWidget(merge_widget)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec_())
728x90
반응형
반응형

안녕하세요.

 

https://coding-yoon.tistory.com/68

 

[파이썬 응용] QT designer to python code ( .ui -> .py) UI파일을 파이썬 코드로 변환

안녕하세요. 강의자료가 전부 PDF이다보니, PDF로 편집할 일이 있었습니다. Adobe 의 pdf를 사용하고 있는데, 무료버젼이다보니 할 수 있는게 별로 없었습니다. 그래서 파이썬으로 필요한 부분만 만�

coding-yoon.tistory.com

PDF 관련 프로그램을 만드는 동기는 위에 적었었고, 오늘은 제가 가장 많이 사용하는 PDF합치기를 사용하기 편하게 QT로 구현하였습니다. 

 

http://hogulab.egloos.com/6340633

 

[Python] PdfMerge - 여러 pdf 하나로 합치기 (GUI 5편 - 최종)

이제 "합치기"를 구현해보자. 해당 버튼의 코드는 다음과 같다. 123456789101112131415161718def merge_PDF(self):         count = self.listWidget.count()  &nb

hogulab.egloos.com

굳이 제가 처음부터 만들지 않았고, 위 블로그의 코드에 맞춰 제작하였습니다. 

 

제가 추가하고, 없앤 기능은 

 

1. 파일을 Drag & Drop을 하여 list에 추가하게끔 바꿨습니다. 

 

저는 마우스로 클릭하는 것보다 파일을 마우스로 드래그해서 갖다놓는 방식이 더 편하다고 생각했습니다. 

 

2. 저장 폴더 설정 버튼 삭제

 

굳이 다운로드 경로를 설정하는 방식은 너무 귀찮아서 없애버렸습니다. 합치기 버튼을 누르면 다운로드 다이얼 로그가 생성되는 방식으로 바꿨습니다. 

 

 

1. 다이얼로그 방식

 

 

정석 방식

2. 파일 드래그 앤 드롭 방식

 

드래그 앤 드롭방식(PDF이외의 파일형식은 올라가지 않음)

 

만약 저장할 PDF가 없다면.

파일 없을 시 

728x90
반응형
반응형

안녕하세요. 

 

강의자료가 전부 PDF이다보니, PDF로 편집할 일이 있었습니다. 

 

Adobe 의 pdf를 사용하고 있는데, 

 

유료버젼을 사용해라...

무료버젼이다보니 할 수 있는게 별로 없었습니다. 

 

그래서 파이썬으로 필요한 부분만 만들어서 할려고 찾아보니 

http://egloos.zum.com/hogulab/v/6340633

 

[Python] PdfMerge - 여러 pdf 하나로 합치기 (GUI 5편 - 최종)

이제 "합치기"를 구현해보자. 해당 버튼의 코드는 다음과 같다. 123456789101112131415161718def merge_PDF(self): count = self.listWidget.count() print(count) output = PdfFileWriter() for x in range

egloos.zum.com

PDF를 합치는 ui 프로그램

ui로 위 사이트에서 깔끔하게 만들어 놓으셨습니다. 

 

코드를 하나씩 확인해보니까 designer로 ui를 만드시고 py로 변환하셨더라구요. 

 

그래서 문뜩 이거를 글로 쓰면 괜찮겠다 싶어 지금 작성하고 있습니다. 

 

우선 파이썬 UI 프로그램 중에 PyQt5가 대표적입니다. 

 

python -m pip install pyqt5

 

pyqt5를 깔게 되면 자동적으로 QT designer가 깔립니다.

 

QT Designer 프로그램입니다. 

아무거나 배치

위젯들을 그냥 아무렇게나 배치하고 저장하겠습니다. 

저장 폴더

폴더 만들어서 ui를 저장했습니다. 

 

cmd를 켜줍니다. 

 

change directory

cmd에서 ui파일이 있는 폴더로 경로를 변경해줍니다. 

 

python -m PyQt5.uic.pyuic -x (ui파일) -o ((py)

 

UI 파일(입력) : untitled.ui

py 파일(출력) : hi.py

 

py생성
ui to py

그러면 손쉽게 자신이 이쁘게 짜놓은 ui를 py로 변환했습니다. 

 

혹시 모르니 실행해보겠습니다.

 

잘 나옵니다.

728x90
반응형
반응형

 

 

안녕하세요. 

 

오늘은 Python에 내장되어 있는 threading과 PyQt5dml QThread의 차이점에 대해 이야기하겠습니다.

 

threading 쓰레드 역할을하고, QThread도 쓰레드 역할을 합니다.

 

하지만 분명히 둘의 차이가 있습니다. 

 

우선, 쓰레드에 대해 애매하시다면 아래 글을 보시면 됩니다.

 

https://coding-yoon.tistory.com/45

 

[파이썬 실습] PyQt5 : QThread를 사용해 응답 없음 방지 & 여러 동작하기

안녕하세요. 프로그래밍을 하면서 여러 동작을 하기 위해서는 쓰레드란 개념을 알아야 합니다. 우선, 작업관리자를 한 번 보겠습니다. CPU는 한 번에 한 가지의 동작밖에 하지 못합니다. 하지만 G(10의 9제곱)단..

coding-yoon.tistory.com

저번 글과 똑같이 QThread에 구현하겠습니다. 

#쓰레드를 선언한 간단한 예제
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import time
import sys


#쓰레드 선언
class Thread1(QThread):
    #parent = MainWidget을 상속 받음.
    def __init__(self, parent=None):
        super().__init__(parent)
    def run(self):
        for i in range(10):
            print("Thread :",i)
            time.sleep(1)


class MainWidget(QWidget):
    def __init__(self):
        super().__init__()
        thread_start = QPushButton("시 작!")
        thread_start.clicked.connect(self.increaseNumber)

        vbox = QVBoxLayout()
        vbox.addWidget(thread_start)

        self.resize(200,200)
        self.setLayout(vbox)

    def increaseNumber(self):
        x = Thread1(self)
        x.start()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    widget = MainWidget()
    widget.show()
    sys.exit(app.exec_())

 

 

 

이번엔 Python threading을 이용해 쓰레드를 구현하겠습니다.

#threading을 이용해 쓰레드 구현
from PyQt5.QtWidgets import *
import threading
import time
import sys


#쓰레드 선언
class Thread1(threading.Thread):
    def __init__(self, parent=None):
        super().__init__(parent)
    def run(self):
        for i in range(10):
            print("Thread :",i)
            time.sleep(1)


class MainWidget(QWidget):
    def __init__(self):
        super().__init__()
        thread_start = QPushButton("시 작!")
        thread_start.clicked.connect(self.increaseNumber)

        vbox = QVBoxLayout()
        vbox.addWidget(thread_start)

        self.resize(200,200)
        self.setLayout(vbox)

    def increaseNumber(self):
        x = Thread1()
        x.start()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    widget = MainWidget()
    widget.show()
    sys.exit(app.exec_())

 

 

두 개의 차이점을 아시겠나요?

 

threading은 gui가 종료되어도 하나의 쓰레드로서 자신의 일을 마칠 때까지 쓰레드가 돌아가는 반면에,

 

QThread는 gui가 꺼지면, 같이 쓰레드가 종료됩니다. 

728x90
반응형
반응형

안녕하세요.

 

프로그래밍을 하면서 여러 동작을 하기 위해서는 쓰레드란 개념을 알아야 합니다. 

 

우선, 작업관리자를 한 번 보겠습니다.

 

작업관리자

CPU는 한 번에 한 가지의 동작밖에 하지 못합니다. 하지만 G(10의 9제곱)단위로 동작합니다.

 

작업관리자를 확인하면 CPU는 하나인 반면, 프로세스는 184개가 1958개의 쓰레드를 통해 동작하는 것을 확인할 수 있습니다.

 

CPU는 시간, 우선순위 등 여러가지 방식으로 할당합니다.

 

예를 들어,

 

간단한 쓰레드 구조

이런식으로 쓰레드 1번 수행, 2번 수행, 다음 3번 수행하면서 반복합니다.

 

그러나 그 속도가 굉장히 빨라 사람들이 사용하는데 알아차리지 못합니다. 

 

#쓰레드를 선언하지 않은 예제
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import time
import sys


class MainWidget(QWidget):
    def __init__(self):
        super().__init__()
        thread_start = QPushButton("시 작!")
        thread_start.clicked.connect(self.increaseNumber)

        vbox = QVBoxLayout()
        vbox.addWidget(thread_start)
		
        self.resize(200, 200)
        self.setLayout(vbox)
	
    #버튼을 누르면 1씩 증가하는 함수
    def increaseNumber(self):
        for i in range(10):
            print("Thread :",i)
            time.sleep(1)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    widget = MainWidget()
    widget.show()
    sys.exit(app.exec_())

쓰레드를 선언하지 않고 버튼을 누르면 0부터 9까지 수행하는 간단한 PyQt5를 예시를 보겠습니다.

 

코딩에서는 쓰레드를 선언하지 않았지만, 사실 여기에는 쓰레드가 사용되고 있습니다. 

 

바로 GUI에서 사용되고 있습니다. 

 

이 프로그램을 돌려 보시면, 버튼을 누르고 함수가 수행을 마칠 때까지 GUI는 동작하지 않습니다.

 

아마 응답하지 않는다고 경고창이 뜰 것입니다. 

 

그 이유는 이 프로그램에 할당된 쓰레드는 하나이고, 이미 함수를 동작하는데 쓰레드가 사용되고 있으니, GUI는 그 동안 동작하지 않습니다. 

 

그렇다면 쓰레드를 한 번 사용해서 GUI도 움직이고, 함수도 동작하는 예제를 작성해보겠습니다.

#쓰레드를 선언한 간단한 예제
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import time
import sys


#쓰레드 선언
class Thread1(QThread):
    #parent = MainWidget을 상속 받음.
    def __init__(self, parent):
        super().__init__(parent)
    def run(self):
        for i in range(10):
            print("Thread :",i)
            time.sleep(1)


class MainWidget(QWidget):
    def __init__(self):
        super().__init__()
        thread_start = QPushButton("시 작!")
        thread_start.clicked.connect(self.increaseNumber)

        vbox = QVBoxLayout()
        vbox.addWidget(thread_start)

        self.resize(200,200)
        self.setLayout(vbox)

    def increaseNumber(self):
        x = Thread1(self)
        x.start()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    widget = MainWidget()
    widget.show()
    sys.exit(app.exec_())

QThread를 선언하고 자신이 실행시키고자 하는 함수를 run에 작성해줍니다. 

 

그리고 선언한 쓰레드 클레스를 객체를 생성해주고 객체를 start해주면 간단하게 해결됩니다.

 

728x90
반응형

+ Recent posts