我们接下来的讨论,会基於读者已经先读过我 day5 文章 的架构下去进行程序设计
如果还不清楚我程序设计的逻辑 (UI.py、controller.py、start.py 分别在干麻)
建议先阅读 day5 文章後再来阅读此文。
https://www.wongwonggoods.com/python/pyqt5-5/
https://github.com/howarder3/ironman2021_PyQt5_photoshop/tree/main/day13_scroll_area
这篇是延续 Day 12 显示图片 zoom in, zoom out 功能的後续开发,
只有 zoom in, zoom out 有时还不足以应付我们处理细节,
因此我们需要一个卷轴,帮助我们能更自由的移动图片。
注意顺序,先新增 Vertical Layout,叠加上 Scroll Area,再叠加上 Qlabel
。注意这些物件彼此之间的阶层关系,一样我们可以先修改一些物件名称,方便我们等等使用
。我们在介面的右下角新增能够显示目前图片的解析度的 Qlabel,
新增这个功能主要是能方便我们能够确定现在图片已经被我们缩放到什麽程度了。
读者们可以开始自行设计自己的介面罗,以上为我的示范。
一样的编译指令,我们加上 -x (也可不加),
我们就可以先检视看看转换後的视窗是不是跟我们想像的一样。
pyuic5 -x day13.ui -o UI.py
一样,这程序只有介面 (视觉上的呈现),没有任何互动功能
python UI.py
这样我们的介面就大致出来罗!
我们先观察一下刚刚在 QtDesigner 中的物件阶层关系,
其中红色框框的地方有多出一个我们不要的东西,scrollAreaWidgetContents,
这个东西在 QtDesigner 中预设是会与 QscrollArea 一起被建立,
但实际上因为我们已经很清楚我们需要的是 Qlabel 显示的图片,
因此我们直接去改 UI.py 里面的一些内容。
我们可以透过搜寻功能帮助我们快速找到相关的段落,这些都是要删掉的
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 667, 427))
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.label = QtWidgets.QLabel(self.scrollAreaWidgetContents)
self.label.setGeometry(QtCore.QRect(0, 0, 1920, 1080))
self.label.setObjectName("label")
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
我们观察一下,
# self.scrollAreaWidgetContents = QtWidgets.QWidget()
# self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 800, 400))
# self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.label = QtWidgets.QLabel()
self.label.setGeometry(QtCore.QRect(0, 0, 0, 0))
self.label.setObjectName("label")
self.scrollArea.setWidget(self.label)
为何不使用 self.scrollAreaWidgetContents?
目前测试的结果是不会成功的显示出卷轴,可能的原因是因为 Qlabel 才有存在超过视窗范围的大小,而 self.scrollAreaWidgetContents 作为容器,并没有办法以超过的大小触发 self.scrollArea 的卷轴事件,因此功能失效。
不过这部份原因目前只是我的猜测,总之卷轴的功能是无法正常运行的。
这次除了 day12 既有的功能之外,我们新增了一些物件,
我们继续修改我们 day12 的程序码
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.ui.scrollArea.setWidgetResizable(True)
self.ui.label.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
# self.ui.label.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter) # 将图片置中
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.img_resize()
def func_zoom_out(self):
self.qpixmap_height += 100
self.img_resize()
def img_resize(self):
scaled_pixmap = self.qpixmap.scaledToHeight(self.qpixmap_height)
print(f"current img shape = ({scaled_pixmap.width()}, {scaled_pixmap.height()})")
self.ui.img_shape.setText(f"current img shape = ({scaled_pixmap.width()}, {scaled_pixmap.height()})")
self.ui.label.setPixmap(scaled_pixmap)
与 day12 的不同是,我们主要新增了这两行
self.ui.scrollArea.setWidgetResizable(True)
self.ui.label.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
# self.ui.label.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter) # 将图片置中
但是如果为了好看,想让图片置中,可以改为以下叙述:
self.ui.label.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
因为我们新增了 UI 优化的功能,稍微想一下就可以知道,
这段程序码基本上会跟着我们图片变化一起改变,
因此我们把「显示图片现在解析度」的功能新增在此处。
照我们 day5 的程序架构,我们执行
python start.py
★ 本文也同步发於我的个人网站(会有内容目录与显示各个小节,阅读起来更流畅):【PyQt5】Day 13 - 使用 QVBoxLayout, QscrollArea 制作出卷轴,以高解析度检视图片 (基於 QImage 使用 OpenCV) PyQt5 scrollable image
>>: Day 13 漏洞分析 - Vulnerability Analysis (unix-privesc-check)
还记得我们很早之前说过Flutter有一个问题就是嵌套太多层时我们要从下层拿到上层的东西时会变得十分...
这次实作的功能是使用Google Book api 使用textfield输入ISBN码按下Butt...
MVC与MVVM MVC MVC是一个前後端架构,分为三个部分: 视图(View),为画面显示的地方...
2021.09.20 ACL( AI人工智慧资料分析软件)原厂Galvanize宣布成功整并为勤奋集...
今天来介绍云端的管理,常常出现的三个名词,在先前的文章中,我应该也有使用过了一部分。这三个名词长的很...