Skip to content

[PyQt5] 拖曳圖片到 Label 元件上並顯示圖片

Last Updated on 2021-05-17 by Clay

在我們開發前端界面的時候,如果我們要將圖片顯示在界面上觀看的話,除了『打開目錄讓使用者選擇』之外,我認為可以直接讓使用者拖曳圖片到界面上顯示是一種非常棒的體驗。

嗯......至少我個人很喜歡啦,哈哈哈。

在 PyQt5 當中要做到這件事情其實也不難,大致上要做的事情只有 3 件:

  1. 讓我們要顯示圖片的元件允許拖曳:setAcceptDrops(True)
  2. 重寫 dragEnterEvent() method: acceptProposedAction() 接受拖曳動作
  3. 重寫 dropEvent() method: 撰寫我們要拖曳之後要做的事情

我學習這種拖曳方法是在以下這個網站,也推薦給大家: http://zetcode.com/gui/pyqt5/dragdrop/

如果對於學習 PyQt5 有興趣,也許可以考慮參考我寫的 PyQt5 系列

那麼,以下就來看段簡單的拖曳並顯示圖片的程式碼吧。


重寫 QLabel

如果說到要如何在 PyQt5 裡面顯示圖片,那當然非 QLabel 這個元件莫屬了。以下,首先就來重寫 QLabel,讓這個元件可以支援拖曳。

還記得剛才我在上方寫的 3 個步驟嗎?

  1. 讓我們要顯示圖片的元件允許拖曳:setAcceptDrops(True)
  2. 重寫 dragEnterEvent() method: acceptProposedAction() 接受拖曳動作
  3. 重寫 dropEvent() method: 撰寫我們要拖曳之後要做的事情
# -*- coding: utf-8 -*-
import re
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *


class dLabel(QLabel):
    def __init__(self, widget):
        super(dLabel, self).__init__(widget)
        self.setAcceptDrops(True)

    def dragEnterEvent(self, event):
        file_name = event.mimeData().text()
        if file_name.split('.')[-1] in ['png', 'jpg', 'jpeg']:
            event.acceptProposedAction()
        else:
            event.ignore()

    def dropEvent(self, event):
        file_path = event.mimeData().text()
        file_path = re.sub('file:///', '', file_path)
        self.setPixmap(QPixmap(file_path))
        self.setScaledContents(True)



首先,將 setAcceptDrops(True) 啟用。

def __init__(self, widget):
    super(dLabel, self).__init__(widget)
    self.setAcceptDrops(True)



然後,重寫 dragEnterEvent()。

def dragEnterEvent(self, event):
    file_name = event.mimeData().text()
    if file_name.split('.')[-1] in ['png', 'jpg', 'jpeg']:
        event.acceptProposedAction()
    else:
        event.ignore()



這裡我做了個限制,只有副檔名為 png、jpg、jpeg 的格式才能夠被接受,其他的檔案都會被忽略。

然後,就是重寫 dropEvent() 了。

def dropEvent(self, event):
    file_path = event.mimeData().text()
    file_path = re.sub('file:///', '', file_path)
    self.setPixmap(QPixmap(file_path))
    self.setScaledContents(True)



我刪除了本來檔案路徑當中會有的 "file:///",因為這是讀取圖片時不需要的部份,刪除完後,就是圖片本身的絕對路徑了。

就這樣,我們重新寫了一個屬於自己『可以拖曳圖片並顯示』的 dLabel,現在我們來測試一下吧。


測試程式

我剛才重新寫好的檔案叫 dropLabel.py,別忘了從那個檔案 import 剛寫好的 dLabel。

# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import *
from dropLabel import dLabel


class MainWindow(QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.resize(800, 600)
        self.setWindowTitle('Drop Event Test')

        self.label = dLabel(self)
        self.label.setGeometry(200, 150, 400, 300)
        self.label.setStyleSheet('background-color: rgb(255, 255, 255);')


if __name__ == '__main__':
    app = QApplication([])
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())



Output:

這個界面上只有 dLabel 這個我們剛重新寫好的元件。現在我們拖曳一個 PNG 檔案到上面。

大功告成!

嗯?你問我說上面那個醜醜的人臉是什麼?唉呀,其實那是我的自畫像,好像有點醜 QAQ。

Leave a Reply