我們接下來的討論,會基於讀者已經先讀過我 day5 文章 的架構下去進行程式設計
如果還不清楚我程式設計的邏輯 (UI.py、controller.py、start.py 分別在幹麻)
建議先閱讀 day5 文章後再來閱讀此文。
https://www.wongwonggoods.com/python/pyqt5-5/
https://github.com/howarder3/ironman2021_PyQt5_photoshop/tree/main/day12_img_resize
這篇是延續 Day 11 顯示圖片的後續開發,
在 day11 我們只是單純的顯示圖片,
但有碰到了「圖片解析度太大,無法完全顯示」的問題,
今天我們就要加入「zoom in」、「zoom out」的功能,來改善這個問題。
我們與之前一樣新增一個 Qlabel,文字可以先不用管他,
這個 Qlabel 是我們等等要作為顯示圖片使用,
因此我們記得要去修改圖片大小,以免顯示的範圍太小。
注意上圖中的圖片大小,另外變數名稱也建議修改。
讀者們可以開始自行設計自己的介面囉,以上為我的示範。
一樣的編譯指令,我們加上 -x (也可不加),
我們就可以先檢視看看轉換後的視窗是不是跟我們想像的一樣。
pyuic5 -x day12.ui -o UI.py
一樣,這程式只有介面 (視覺上的呈現),沒有任何互動功能
python UI.py
這樣我們的介面就大致出來囉!
這次我們有三個物件
還記得我們在 day5 中的模板嗎?這邊我們直接複製過來使用並修改。
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QFileDialog
import cv2
from UI import Ui_MainWindow
class MainWindow_controller(QtWidgets.QMainWindow):
def __init__(self):
super().__init__() # in python3, super(Class, self).xxx = super().xxx
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.setup_control()
def setup_control(self):
# TODO
self.img_path = 'cat.jpg'
self.ui.btn_zoom_in.clicked.connect(self.func_zoom_in)
self.ui.btn_zoom_out.clicked.connect(self.func_zoom_out)
self.display_img()
def display_img(self):
self.img = cv2.imread(self.img_path)
height, width, channel = self.img.shape
bytesPerline = 3 * width
self.qimg = QImage(self.img, width, height, bytesPerline, QImage.Format_RGB888).rgbSwapped()
self.qpixmap = QPixmap.fromImage(self.qimg)
self.qpixmap_height = self.qpixmap.height()
self.ui.label.setPixmap(QPixmap.fromImage(self.qimg))
def func_zoom_in(self):
self.qpixmap_height -= 100
self.resize_image()
def func_zoom_out(self):
self.qpixmap_height += 100
self.resize_image()
def resize_image(self):
scaled_pixmap = self.qpixmap.scaledToHeight(self.qpixmap_height)
self.ui.label.setPixmap(scaled_pixmap)
相關的功能我們在 day11,
有介紹的很詳細了,這邊只說我們有修改的部份
會修改的原因主要是我們新增了 zoom in 的功能,
因此我們顯示圖片函式需要調整成可以隨時變動的 (不寫死、保有彈性,可重複使用)
我們把原先的寫的內容拆解,
特別其中的這四行:
self.qimg = QImage(self.img, width, height, bytesPerline, QImage.Format_RGB888).rgbSwapped()
self.qpixmap = QPixmap.fromImage(self.qimg)
self.qpixmap_height = self.qpixmap.height()
self.ui.label.setPixmap(QPixmap.fromImage(self.qimg))
第一行一樣我們透過 OpenCV 的方式,轉換成我們要的 Qimage
第二行我們改成獨立從 Qimage 提取出 QPixmap,
這邊我們可以理解為
我們在第三行取得 QPixmap 的高度,作為我們等等縮放使用
最後第一行一樣就是透過 label 顯示出來。
這邊我們是去調整「我們想要呈現的」QPixmap 高度,
在接下來的 resize_image() ,讓他依據這個高度自動比例縮放。
scaled_pixmap = self.qpixmap.scaledToHeight(self.qpixmap_height)
self.ui.label.setPixmap(scaled_pixmap)
這邊的第一行就是讓圖片 (Qpixmap) 自己去適應我們要的圖片高度,做出對應的圖片縮放。
而第二行就是把縮放後的圖片 (Qpixmap) 塞進去我們的 label 當中。
注意:我們從頭到尾都只有更改到 Qpixmap 而沒有改動到 Qimg,
這也表示我們的原圖是一直有被保存下來的。
我們所做的都只是「顯示上的更動
」。
照我們 day5 的程式架構,我們執行
python start.py
★ 本文也同步發於我的個人網站(會有內容目錄與顯示各個小節,閱讀起來更流暢):【PyQt5】Day 12 - 建立一個可以縮放圖片大小的顯示器 (基於 QImage 使用 OpenCV)