QMimeDataにファイルのデータをセットしてみる

2022/02/09 categories:Python| tags:Python|QMimeData|PyQt5|

PyQt5のQMimeDataにファイルのデータをセットするプログラムを作ってみました。

処理内容

QMimeDataにPNGファイルをセットする場合は、以下のようなコードです。

def load_file(self, filename):
    stream = QtCore.QFile(filename)
    stream.open(QtCore.QFile.ReadOnly)
    data = stream.readAll()
    stream.close()
    return data

mime_data = QtCore.QMimeData()
mime_data.setData( 'image/png', self.load_file('test01.png') )
mime_data.setUrls([ QtCore.QUrl().fromLocalFile('test01.png') ])

QtCore.QMimeData().setData()にmimeタイプとデータのQByteArrayを渡して、setUrls()でファイルのパスをQUrlとして渡すとデータをセットできます。ファイルのデータをQByteArrayに変換するには、QFile()のreadAll()を使うとよいようです。

QMimeDataからセットしたデータを取得できるか確認するために、QDropEventを使用してデータを取得するプログラムを作成して確認しました。

実行結果

ボタンをクリックするとローカルにあるファイルをQMimeDataにセットしてからdropEventを実行して、dropEventの処理内でwidgetへデータを表示しています。

Pythonコード

import sys
from pathlib import Path
from PyQt5 import QtWidgets, QtCore, QtGui

class Widget(QtWidgets.QWidget):
    def __init__(self):
        super(Widget, self).__init__()
        self.resize(620, 500)
        self.setWindowTitle('QMimeData test')
        self.view0, self.view1 = QtWidgets.QGraphicsView(), QtWidgets.QGraphicsView()
        self.text0, self.text1 = QtWidgets.QTextEdit(), QtWidgets.QTextEdit()
        self.button0, self.button1 = QtWidgets.QPushButton('Drop test image'), QtWidgets.QPushButton('Drop test text')
        self.setLayout( QtWidgets.QGridLayout(self) )
        self.layout().setContentsMargins(0, 0, 0, 0)
        self.layout().addWidget(self.button0, 0, 0, 1, 1)
        self.layout().addWidget(self.button1, 0, 1, 1, 1)
        self.layout().addWidget(self.view0,   1, 0, 1, 1)
        self.layout().addWidget(self.text0,   1, 1, 1, 1)
        self.layout().addWidget(self.view1,   2, 0, 1, 1)
        self.layout().addWidget(self.text1,   2, 1, 1, 1)

        self.view0.setScene( QtWidgets.QGraphicsScene() )
        self.view1.setScene( QtWidgets.QGraphicsScene() )

        self.button0.clicked.connect(self.drop_test0)
        self.button1.clicked.connect(self.drop_test1)

    def load_file(self, filename):
        stream = QtCore.QFile(filename)
        stream.open(QtCore.QFile.ReadOnly)
        data = stream.readAll()
        stream.close()
        return data

    def drop_test0(self):
        self.view0.scene().clear(), self.view1.scene().clear(), self.text0.clear(), self.text1.clear()
        mime_data = QtCore.QMimeData()
        mime_data.setData( 'image/png', self.load_file('test01.png') )
        mime_data.setData( 'image/jpeg', self.load_file('test02.jpg') )
        mime_data.setUrls([ QtCore.QUrl().fromLocalFile('test01.png'), QtCore.QUrl().fromLocalFile('test02.jpg') ])

        drop_event = QtGui.QDropEvent(
            QtCore.QPointF(0.0, 0.0), QtCore.Qt.DropAction.MoveAction,
            mime_data, QtCore.Qt.MouseButton.LeftButton, QtCore.Qt.KeyboardModifier.NoModifier
        )
        self.dropEvent(drop_event)

    def drop_test1(self):
        self.view0.scene().clear(), self.view1.scene().clear(), self.text0.clear(), self.text1.clear()
        mime_data = QtCore.QMimeData()
        mime_data.setData('text/plain', self.load_file('test01.txt') )
        mime_data.setData('text/plain', self.load_file('test02.txt') )
        mime_data.setUrls([ QtCore.QUrl().fromLocalFile('test01.txt'), QtCore.QUrl().fromLocalFile('test02.txt') ])

        drop_event = QtGui.QDropEvent(
            QtCore.QPointF(0.0, 0.0), QtCore.Qt.DropAction.MoveAction,
            mime_data, QtCore.Qt.MouseButton.LeftButton, QtCore.Qt.KeyboardModifier.NoModifier
        )
        self.dropEvent(drop_event)

    def dropEvent(self, event: QtGui.QDropEvent) -> None:
        if event.mimeData().hasUrls():
            paths = [ url.toLocalFile() for url in event.mimeData().urls() ]
            if '.png' in [ Path(p).suffix for p in paths ]:
                self.view0.scene().addPixmap( QtGui.QPixmap(paths[0]) )
                self.view1.scene().addPixmap( QtGui.QPixmap(paths[1]) )
            else:
                with open(paths[0], mode='r') as f:
                    self.text0.setText( f.read() )
                with open(paths[1], mode='r') as f:
                    self.text1.setText( f.read() )

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    widget = Widget()
    widget.show()
    app.exec()

Share post

Related Posts

コメント