Pyside6:开发一个自适应的图片控件

news2024/11/28 9:22:49

在Qt中最简单展示图片用的控件是QLabel,但这个控件使用起来非常不方便,没有添加自适应的时候:

可以发现该图片是按真实像素来展示的,因此图片如果过大,只能展示局部。那么添加自适应后,变化又会出现:

虽然看到的图片是局部的,和之前区别只是平铺了,但其实这个是Qt Designer的bug,当你再次去修改窗口大小的时候,你会发现整个窗口大小将变成图片真实大小,且窗口只能放大,无法缩小:

图片过大,需要滚动才可以展示。

所以开发一个简单实用的自适应图片控件用以处理这些问题很有必要。(如果不想看思路的,直接看完整代码。)

一、思路

思路其实非常简单,Qt中有一个QFrame可以承载其他控件,当QFrame的大小改变时,将QFrame中的控件大小也进行改变。因此把QLabel加入到QFrame中即可完成功能。

1.1 开发前提

QLabel中有一个属性scaledContents,它允许图片可以随意拉伸:

可以看到,当打开scaledContents图片即可拉伸,关闭即无法拉伸。

二、开发 

2.1 定义自定义类

from PySide6.QtWidgets import QFrame

class QFitImage(QFrame):
    pass

将该类名取名为QFitImage,该类继承于QFrame,这样我可以在Qt Designer将QFrame进行提升。

2.2 添加QLabel

from PySide6.QtWidgets import QFrame, QLabel
from PySide6.QtGui import QPixmap


class QFitImage(QFrame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.image_label = QLabel(self)
        self.image_label.setScaledContents(True)

将QLabel添加到QFrame上并打开scaledContents。

2.3 设置图片 

设置图片将采用资源文件文本添加图片的形式,因此设置一个set方法并创建一个QPixmap:

    def set_image(self, file_name):
        pix_map = QPixmap(file_name)
        self.image_label.setPixmap(pix_map)

2.4 获取图片宽高比 

每次获取图片时,获取图片的宽高比,以此来判断图片需要设置的大小:

    def set_image(self, file_name):
        pix_map = QPixmap(file_name)
        self.image_rate = pix_map.width() / pix_map.height()
        self.image_label.setPixmap(pix_map)

2.5 计算图片宽高 

    def compute_size(self):
        if self.image_rate is not None:
            w = self.size().width()
            h = self.size().height()
            scale_w = int(h * self.image_rate)

            if scale_w <= w:
                self.image_label.resize(QSize(scale_w, h))
            else:
                scale_h = int(w / self.image_rate)
                self.image_label.resize(QSize(w, scale_h))
        else:
            self.image_label.resize(self.size())

通过QFrame的大小来计算图片所需的宽高,然后在相应的地方调用即可:

    def set_image(self, file_name):
        ...

        self.compute_size()

    def resizeEvent(self, event):
        super().resizeEvent(event)
        self.compute_size()

通过一个示例查看一下现在的情况:

表现的不错,不过图片一直在左上方,我们将它挪到中间来。

2.6 图片挪到中间 

    def compute_size(self):
        if self.image_rate is not None:
            w = self.size().width()
            h = self.size().height()
            scale_w = int(h * self.image_rate)

            if scale_w <= w:
                self.image_label.resize(QSize(scale_w, h))
                self.image_label.setProperty("pos", QPoint(int((w - scale_w) / 2), 0))
            else:
                scale_h = int(w / self.image_rate)
                self.image_label.resize(QSize(w, scale_h))
                self.image_label.setProperty("pos", QPoint(0, int((h - scale_h) / 2)))
        else:
            self.image_label.resize(self.size())

 通过计算大小来修改位置,以达到图片居中的方式,可以看到已经完美居中了:

三、完整代码 

# -*- coding: utf-8 -*-
from PySide6.QtWidgets import QFrame, QLabel
from PySide6.QtGui import QPixmap
from PySide6.QtCore import QSize, QPoint


class QFitImage(QFrame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.image_label = QLabel(self)
        self.image_label.setScaledContents(True)

        self.image_rate = None

    def set_image(self, file_name):
        try:
            pix_map = QPixmap(file_name)
            self.image_rate = pix_map.width() / pix_map.height()
            self.image_label.setPixmap(pix_map)
            self.compute_size()
        except:
            pass

    def compute_size(self):
        if self.image_rate is not None:
            w = self.size().width()
            h = self.size().height()
            scale_w = int(h * self.image_rate)

            if scale_w <= w:
                self.image_label.resize(QSize(scale_w, h))
                self.image_label.setProperty("pos", QPoint(int((w - scale_w) / 2), 0))
            else:
                scale_h = int(w / self.image_rate)
                self.image_label.resize(QSize(w, scale_h))
                self.image_label.setProperty("pos", QPoint(0, int((h - scale_h) / 2)))
        else:
            self.image_label.resize(self.size())

    def resizeEvent(self, event):
        super().resizeEvent(event)
        self.compute_size()

四、总结

扩展一个自适应的图片控件不仅仅这么一个方法,本文仅提供其中一个思路,并且本文中有不少方法可以运用在大部分扩展控件的方法中,例如setProperty,调用父类Event方法等等,熟练掌握这些技术可以完成许许多多你想要的功能。

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1041999.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

简单但好用:4种Selenium截图方法了解一下!

前言 我们执行UI自动化操作时&#xff0c;大多数时间都是不在现场的&#xff0c;出现错误时&#xff0c;没有办法第一时间查看到&#xff0c;这时我们可以通过截图当时出错的场景保存下来&#xff0c;后面进行查看报错的原因&#xff0c;Selenium中提供了几种截图的方法&#…

spring bean实例化过程及顺序

spring bean的初始化从doCreateBean方法开始&#xff0c;依次会调用下面三个方法执行bean的初始化。大部分方法都在AbstractAutowireCapableBeanFactory类中。 实例化 createBeanInstance()方法根据BeanDef获取bean对应的class通过反射调用构造函数进行bean的实例化。 这里会…

C语言的stdio.h的介绍

C语言的stdio.h的介绍 C语言的stdio.h的介绍 C语言的stdio.h的介绍C语言stdio.h的介绍 C语言stdio.h的介绍 这个含义是导入标准输入输出库 包含头文件.h&#xff0c;std标准库&#xff0c;io是input output输入输出库 <>代表系统库&#xff0c;自定义的话用""…

Android Jetpack Compose之确定重组范围并优化重组

目录 1.概述2.确定Composable重组的范围3.优化重组的性能3.1 Composable 位置索引3.2 通过Key添加索引信息3.3 使用注解Stable优化重组 1.概述 前面的文章提到Compose的重组是智能的&#xff0c;Composable函数在进行重组时会尽可能的跳过不必要的重组&#xff0c;只对需要变化…

C语言中结构体,枚举,联合相关介绍

本次重点&#xff1a; 1、结构体 &#xff1a; &#xff08;1&#xff09;结构体类型的声明 &#xff08;2&#xff09;结构的自引用 &#xff08;3&#xff09;结构体变量的定义和初始化 &#xff08;4&#xff09;结构体内存对齐 &#xff08;5&#xff09;结构体传参 …

干细胞液氮容器选择与使用

干细胞液氮容器的使用非常重要&#xff0c;以确保干细胞样品在冷冻和储存过程中的有效性和安全性。以下是使用干细胞液氮容器时需要注意的事项&#xff1a; 1、容器选择&#xff1a;选择合适的容器非常重要。容器应具有良好的密封性能和耐腐蚀性&#xff0c;以避免外部空气和污…

01-Zookeeper特性与节点数据类型详解

上一篇&#xff1a; 在了解Zookeeper之前&#xff0c;需要对分布式相关知识有一定了解&#xff0c;什么是分布式系统呢&#xff1f;通常情况下&#xff0c;单个物理节点很容易达到性能&#xff0c;计算或者容量的瓶颈&#xff0c;所以这个时候就需要多个物理节点来共同完成某项…

Oracle VM VirtualBox安装并下载安装CentOS7

Oracle VM VirtualBox安装并下载安装CentOS7 Oracle VM VirtualBox下载CentOS创建虚拟机 Oracle VM VirtualBox VM下载链接 https://www.oracle.com/cn/virtualization/virtualbox/ 点击链接直接下载就行&#xff0c;下载完默认安装或者更改一下安装目录。 下载CentOS http://…

服务网格概述

引言 2016 年前后&#xff0c;"服务网格"这个词出现在微服务、云计算和 DevOps 的领域。Buoyant 团队在 2016 年用这个词来解释他们的产品 Linkerd。服务网格的到来主要是由于 IT 领域内的一场风暴。开发人员开始使用多语言&#xff08;polyglot&#xff09;方法构建…

古彝文识别:文化遗产的数字化之旅

目录 &#x1f345;前言&#x1f353;古彝文介绍&#x1f353;古彝文识别的重难点&#x1f352;原籍难以获取&#xff0c;传统翻译过程繁琐&#xff0c;周期长。&#x1f352;版式多样&#xff0c;笔画相近。&#x1f352;图像质量差&#xff0c;手写识别难。&#x1f352;古彜…

第二证券:迎政策助力,新型工业化爆发,德恩精工3日涨超60%

新式工业化概念26日盘中大幅拉升&#xff0c;到发稿&#xff0c;德恩精工、精伦电子、天永智能等涨停&#xff0c;固高科技涨约8%&#xff0c;亚威股份涨逾6%&#xff0c;金自天正、创世纪涨约5%。 值得注意的是&#xff0c;精伦电子已接连5个交易日涨停&#xff0c;公司昨日晚…

Mac菜单栏图标管理工具:Bartender 5 完美兼容MacOS Sonoma 14系统

Bartender 5 是一款流行的软件程序&#xff0c;专为酒店行业的调酒师和专业人士设计。它提供了一系列功能和工具来简化酒吧或餐厅的饮料订单、库存和客户偏好的管理流程。Bartender 5 的一些主要功能包括&#xff1a; 1. 饮料配方&#xff1a;该软件包括一个全面的饮料配方数据…

计算机丢失msvcp140_1.dll的解决办法,丢失msvcp140_1.dll的原因

丢失 msvcp140_1.dll 是一个常见的错误信息&#xff0c;通常会在尝试运行某些程序时出现。msvcp140_1.dll 是一个动态链接库文件&#xff0c;它包含了许多 C标准库函数的实现&#xff0c;这些函数在许多程序中都是必需的。因此&#xff0c;如果丢失了该文件&#xff0c;程序可能…

【MySQL基础 | 中秋特辑】多表查询详细总结

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【MySQL学习专栏】&#x1f388; 本专栏旨在分享学习MySQL的一点学习心得&#xff0c;欢迎大家在评论区讨论&#x1f48c; 目录 一、多表…

如何解决跨浏览器兼容性问题?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 解决跨浏览器兼容性问题⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量…

台式多参数水质测定仪可以测哪些污水

台式污水测定仪可以测哪些污水&#xff1a; 1.废水处理厂监测&#xff1a;废水处理厂需要定期监测废水中的污染物浓度&#xff0c;包括COD、氨氮、总磷和总氮等指标。台式废水检测仪可以提供快速、准确的检测结果&#xff0c;帮助废水处理厂了解废水处理效果&#xff0c;以便进…

大数据Flink(八十七):DML:Joins之Regular Join

文章目录 DML:Joins之Regular Join DML:Joins之Regular Join Flink 也支持了非常多的数据 Join 方式,主要包括以下三种: 动态表(流)与动态表(流)的 Join动态表(流)与外部维表(比如 Redis)的 Join动态表字段的列转行(一种特殊的 Join)细分 Flink SQL 支持的

《学术小白学习之路》DTM主题动态模型构建

《学术小白学习之路》DTM主题动态模型构建 一、LDA与DTM的区别二、代码实操2.1 数据2.2 获取数据向量2.3 参数设置与模型构建2.4 结果的输出一、LDA与DTM的区别 LDA主题模型主要针对一段段的文档 可以得出每个主题,所对应主题词的词语的概率 该模型的主题概率的生成是基于文…

泰国数字加密平台Bitkub创始人到访上海和数集团

2023年9月21日&#xff0c;泰国数字加密货币交易平台Bitkub创始人兼首席执行官&#xff08;CEO&#xff09;Jirayut Srupsrisopa (Topp)先生到访上海和数集团总部。董事长唐毅先生热情会见了来宾&#xff0c;双方进行了友好深入的交流。 和数集团国际部经理晋松&#xff1b;苏州…

【Linux】计算机的软硬件体系结构

文章目录 一、冯诺依曼体系结构二、操作系统(Operator System)1.操作系统的概念2.为什么要有操作系统3.操作系统如何进行管理 三、系统调用和用户操作接口1.系统调用接口2.用户操作接口 四、计算机的软硬件体系结构 一、冯诺依曼体系结构 目前我们常见的计算机&#xff0c;如笔…