본문 바로가기
  • 야근없는 삶을 위하여
파이썬

Python 이미지 세로로 합치기 - 9 (Drag&Drop 구현하기)

by 우당코 2024. 3. 14.
반응형

이미지 파일을 폴더에서 선택하게 하는 창이 나오게 하는 것도 괜찮지만

그냥 이미지를 그대로 드래그하면 인식되게 하는 것이 더 편리하다.

 

아직 디자인한 코드를 파이참으로 가져오지 않았다면 아래 링크 참고

 

Python 이미지 세로로 합치기 - 8 (파이썬에 불러오기)

디자인이 완료되었다면 그 코드를 파이썬에 불러와 보자. 아직 디자인을 완료하지 않았다면 아래 링크 참고 Python 이미지 세로로 합치기 - 7 (GUI 디자인하기) Part 2. GUI 디자인하기 - Qtdesigner 사용

udangco-coding-record.tistory.com

 

이미지 파일을 Drag & Drop으로 인식되게 만들기

1. 필요한 모듈 import

시작하기 앞서 필요한 모듈을 먼저 import 하자.

import os
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import QSize, Qt, QMimeDatabase
from PyQt5.QtWidgets import QMainWindow, QMessageBox, QListWidget

코드를 작성하다가 필요하면 집어 넣으면 되지만 번거로우므로 한 번에 import 시켜 놓자.

 

2. List widget 변경하기

이미지 넣는 곳을 list widget을 사용했다.

이것을 Drag & Drop이 가능하도록 변경할 것이다.

ListBoxWidget을 새로 만들어서 QListWidget을 약간 변형하는 코드이다.

a. 기본 토대를 만들자.

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()
        else:
            event.ignore()

setAcceptDrop(True)로 Drop하는 액션을 허용하고

각 Drage Enter, Move, drop을 했을 경우 어떻게 해야 하는지 정의했다.

 

이 위젯으로 drag를 하면 dragEnterEvent가 먼저 실행된다.

그리고 DragMoveEvent가 실행되면서 가져오게 되고

dropEvent를 통해서 가져온 내용을 drop 했을 때 실행되는 내용이다.

 

mimData란 가져온 파일의 정보를 알아보는 것이고

hasUrls은 파일 경로로 가져와서 처리할 예정이므로

url 형태인지를 확인하려 사용하는 것이다. (pyqt에 포함된 함수)

 

if, else라는 새로운 녀석이 나왔는데 아직 if를 잘 모른다면 아래 글 참고

 

파이썬 if문

파이썬의 조건문 if 파이썬에서 조건문을 사용해 보자. 이미 좋은 글들이 인터넷에 많이 있다. 자세한 내용을 알고 싶다면 아래 링크를 참고하자. 03-1 if문 먼저 대표적인 조건문인 if 문부터 알아

udangco-coding-record.tistory.com

 

실행해서 파일을 드래그해보면 x 표시가 생긴다.

다음 단계로 가자.

 

3. ListBoxWidget을 적용시키자.

a. setupUi 부분에서 listWidget의 Qtwidgets.QListWidget을 찾아라.

b. Qtwidgets.QListWidget을 ListBoxWidget으로 변경해야 한다.

self.listWidget = ListBoxWidget(self.groupBox_3)

 

이제 실행해 보면 + 가 생기고 들어가는 것 같지만 변화가 없다.

 

들어온 정보들을 화면에 나오도록 처리를 해야 한다.

 

c. 파일 보이게 하기

def dropEvent(self, event): 함수를 아래 코드로 변경하자.

    def dropEvent(self, event):
        if event.mimeData().hasUrls():
            event.setDropAction(Qt.CopyAction)
            event.accept()
            files = event.mimeData().urls()  #파일 경로를 가져오도록 하자.
            for file in files:
                show_file = QtWidgets.QListWidgetItem(str(file.toLocalFile())) # 화면에 표시하기 위한 아이템으로 만들고
                self.addItem(show_file) # 화면에 표시하자
        else:
            event.ignore()

 

event.mimData().urls(): Qt 형식으로 들어오는 것을 파일 경로로 뽑아서

QtWidgets.QListWidgetItem: 화면에 표시하기 위한 형식으로 바꿔주고

str(file.toLocalFile()): 스트링 형태로 파일 경로만 표시하라고 하고

self.addItem(show_file) 화면에 추가하라는 의미

 

d. 테스트

잘 적용되었는지 확인해 보자.

파일의 경로가 리스트 위젯에 표시된다

 

 

전체코드

import os
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import QSize, Qt, QMimeDatabase
from PyQt5.QtWidgets import QMainWindow, QMessageBox, QListWidget


# drag and drop event. 파일 위치 경로를 가져오기
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()
            files = event.mimeData().urls()
            for file in files:
                show_file = QtWidgets.QListWidgetItem(str(file.toLocalFile()))
                self.addItem(show_file)
        else:
            event.ignore()


class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(690, 641)
        self.groupBox = QtWidgets.QGroupBox(Form)
        self.groupBox.setGeometry(QtCore.QRect(30, 30, 631, 51))
        self.groupBox.setObjectName("groupBox")
        self.lineEdit = QtWidgets.QLineEdit(self.groupBox)
        self.lineEdit.setGeometry(QtCore.QRect(10, 20, 151, 20))
        self.lineEdit.setObjectName("lineEdit")
        self.groupBox_2 = QtWidgets.QGroupBox(Form)
        self.groupBox_2.setGeometry(QtCore.QRect(30, 90, 631, 51))
        self.groupBox_2.setObjectName("groupBox_2")
        self.lineEdit_2 = QtWidgets.QLineEdit(self.groupBox_2)
        self.lineEdit_2.setGeometry(QtCore.QRect(10, 20, 541, 20))
        self.lineEdit_2.setObjectName("lineEdit_2")
        self.groupBox_3 = QtWidgets.QGroupBox(Form)
        self.groupBox_3.setGeometry(QtCore.QRect(30, 150, 631, 411))
        self.groupBox_3.setObjectName("groupBox_3")
        self.listWidget = ListBoxWidget(self.groupBox_3)
        self.listWidget.setGeometry(QtCore.QRect(10, 20, 511, 371))
        self.listWidget.setObjectName("listWidget")
        self.pushButton = QtWidgets.QPushButton(self.groupBox_3)
        self.pushButton.setGeometry(QtCore.QRect(540, 20, 75, 23))
        self.pushButton.setObjectName("pushButton")
        self.pushButton_2 = QtWidgets.QPushButton(self.groupBox_3)
        self.pushButton_2.setGeometry(QtCore.QRect(540, 50, 75, 23))
        self.pushButton_2.setObjectName("pushButton_2")
        self.pushButton_3 = QtWidgets.QPushButton(self.groupBox_3)
        self.pushButton_3.setGeometry(QtCore.QRect(540, 80, 75, 23))
        self.pushButton_3.setObjectName("pushButton_3")
        self.pushButton_4 = QtWidgets.QPushButton(Form)
        self.pushButton_4.setGeometry(QtCore.QRect(40, 570, 511, 41))
        self.pushButton_4.setObjectName("pushButton_4")
        self.pushButton_5 = QtWidgets.QPushButton(Form)
        self.pushButton_5.setGeometry(QtCore.QRect(570, 570, 71, 41))
        self.pushButton_5.setObjectName("pushButton_5")

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "이미지 합치기 v1.0"))
        self.groupBox.setTitle(_translate("Form", "가로 사이즈 (px)"))
        self.groupBox_2.setTitle(_translate("Form", "파일명"))
        self.lineEdit_2.setPlaceholderText(_translate("Form", "확장자를 제외한 파일명을 입력해 주세요."))
        self.groupBox_3.setTitle(_translate("Form", "이미지"))
        self.pushButton.setText(_translate("Form", "위 이동"))
        self.pushButton_2.setText(_translate("Form", "아래 이동"))
        self.pushButton_3.setText(_translate("Form", "제거"))
        self.pushButton_4.setText(_translate("Form", "합치기"))
        self.pushButton_5.setText(_translate("Form", "초기화"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Form = QtWidgets.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())

 

여기서 그대로 사용해도 되지만 이미지 파일이 아닌 다른 파일도 리스트위젯으로 들어간다.

 

다음 시간에는 다른 파일은 걸러내고 이미지 파일만 들어가도록 만들어 보자.

 

Python 이미지 세로로 합치기 - 10 (이미지 파일 필터)

이미지 파일만 드래그 되도록 만들어 보자. 폴더에 있는 파일을 전체 선택해서 드래그해서 리스트 위젯에 넣더라도 프로그램이 자동으로 이미지파일만 선별해서 넣도록 해보자. 1. 함수 생성 a.

udangco-coding-record.tistory.com

 

반응형