Python | ドラッグアンドドロップ(Drag and Drop)してパスを抽出する方法

GUI App

PythonのGUIアプリでドラッグアンドドロップ(Drag and Drop)してパスを抽出する方法を説明する。

完成イメージ

ヨシヒコにさとりのしょをドラッグ&ドロップするとけんじゃになるアプリを作る。

コード例

  1. urllib.parseをimportする。
  2. self.setAcceptDrops(True)と設定する。
  3. dragEnterEventaccept()を設定する。
  4. dropEventaccept()を設定し、ドロップ後に行う処理を記述する。
#!/usr/bin/env python3

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QLabel
from PyQt6.QtGui import QPainter
import urllib.parse                                                    # 1


class GuiWindow(QWidget):

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setGeometry(0, 0, 300, 300)
        self.build_ui()
        self.setAcceptDrops(True)                                      # 2

    def build_ui(self):
        self.qlb_なまえ = QLabel('ヨシヒコ', self)
        self.qlb_なまえ.setGeometry(40, 30, 250, 20)

        self.しょくぎょう = 'ゆうしゃ'
        self.qlb_しょくぎょう = QLabel('しょくぎょう : ' + self.しょくぎょう, self)
        self.qlb_しょくぎょう.setGeometry(40, 80, 250, 20)

        self.qlb_どうぐ = QLabel('どうぐ : ', self)
        self.qlb_どうぐ.setGeometry(40, 130, 250, 20)

        self.qlb_メッセージ = QLabel('', self)
        self.qlb_メッセージ.setGeometry(40, 230, 250, 50)

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.drawRoundedRect(25, 20, 250, 200, 10, 10)
        painter.drawLine(40, 63, 260, 63)

    def dragEnterEvent(self, event):                                   # 3
        event.accept()

    def dropEvent(self, event):                                        # 4
        event.accept()
        self.a_QMimeData      = event.mimeData()
        self.b_バイナリ_CRLF    = self.a_QMimeData.data('text/uri-list')
        self.c_バイナリ         = self.b_バイナリ_CRLF.simplified()
        self.d_文字列_パーセント = str(self.c_バイナリ, 'utf-8')
        self.e_文字列          = urllib.parse.unquote(self.d_文字列_パーセント)
        self.f_パス            = self.パス分割(self.e_文字列)
        self.g_ファイル名       = self.ファイル名抽出(self.f_パス)
        self.しょくぎょうを更新()
        self.どうぐを更新(self.g_ファイル名)
        self.メッセージを更新(self.g_ファイル名)

    def パス分割(self, 分割したい文字列):
        file_path = 分割したい文字列
        # 分割用マーキング Windows
        file_path = file_path.replace('file:///C', '|:div:|C')
        file_path = file_path.replace('file:///D', '|:div:|D')
        file_path = file_path.replace('file:///E', '|:div:|E')
        file_path = file_path.replace('file:///F', '|:div:|F')
        # 分割用マーキング Mac
        file_path = file_path.replace('file:///', '|:div:|/')
        # 分割用マーキング server
        file_path = file_path.replace('file:', '|:div:|')
        # マーキングで分割
        file_path = file_path.split(' |:div:|')
        # 1要素目に残った|:div:|を削除
        file_path[0] = file_path[0].replace('|:div:|', '')
        file_path.sort()
        file_path = file_path[0]
        return file_path

    def ファイル名抽出(self, ファイルパス):
        ファイルと拡張子 = ファイルパス.split('/')[-1]
        ファイル名 = ファイルと拡張子.split('.')[0]
        return ファイル名

    def しょくぎょうを更新(self):
        self.しょくぎょう = 'けんじゃ'
        self.qlb_しょくぎょう.setText('しょくぎょう : ' + self.しょくぎょう)

    def どうぐを更新(self, どうぐ):
        self.qlb_どうぐ.setText('どうぐ : ' + どうぐ)

    def メッセージを更新(self, どうぐ):
        self.qlb_メッセージ.setText('ヨシヒコは ' + どうぐ +' を読んだ\n'\
                            'ヨシヒコは けんじゃ になった')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = GuiWindow()
    window.show()
    sys.exit(app.exec())

パスの抽出

手順#4でパスを抽出している。各変数の中身は下記の通り。

self.a_QMimeData<PyQt6.QtCore.QMimeData object at 0x*********>
self.b_バイナリ_CRLFb’file:///Users/yoshihiko/Desktop/%E3%81%95%E3%81%A8%E3%82%8A%E3%81%AE%E3%81%97%E3%82%87.pdf\r\n’
self.c_バイナリb’file:///Users/yoshihiko/Desktop/%E3%81%95%E3%81%A8%E3%82%8A%E3%81%AE%E3%81%97%E3%82%87.pdf’
self.d_文字列_パーセントfile:///Users/yoshihiko/Desktop/%E3%81%95%E3%81%A8%E3%82%8A%E3%81%AE%E3%81%97%E3%82%87.pdf
self.e_文字列file:///Users/yoshihiko/Desktop/さとりのしょ.pdf
self.f_パス/Users/yoshihiko/Desktop/さとりのしょ.pdf
self.g_ファイル名さとりのしょ

例題

ヨシヒコに石川梨華の写真集をドラッグ&ドロップするとけんじゃになるアプリを作成しろ。

まとめ

D&Dでパスを抽出する方法を説明した。

コメント