【问题标题】:PYQT5: Prevent image label changing window sizePYQT5:防止图像标签改变窗口大小
【发布时间】:2021-06-16 05:18:11
【问题描述】:

我正在创建一个简单的图像查看器,它能够使用左/右箭头键循环浏览图像列表。问题是当序列中出现更大的图像时,窗口大小也会变大。我希望图像变小以适应窗口大小,而不是相反。另外,我想让它在用户调整窗口大小时改变它的大小(尽管永远不会大于它的原始大小)。我将如何去做这些?

import sys
import os
import time

from PyQt5 import QtWidgets as qtw
from PyQt5 import QtGui as qtg
from PyQt5 import QtCore as qtc

class MainWindow(qtw.QMainWindow):
    def __init__(self):
        super().__init__()
        self.image_label = qtw.QLabel(alignment=qtc.Qt.AlignCenter)
        self.image_handler()
        self.curr_img = self.images[0]
        self.curr_img_pixmap = qtg.QPixmap(os.path.join(r'C:\Desktop\Python\images', self.curr_img))
        self.resize_image(0)
        self.image_label.setPixmap(self.curr_img_pixmap)
        self.viewer()
        self.setCentralWidget(self.viewer_widget)
        self.setStyleSheet("""* {
            background-color: #0d0d0d;
        }
        .QLabel {
            border-style: none;
        }
        .QMainWindow {
            border-style: none;
        }
        """)
        self.show()

    def image_handler(self):
        self.images = [image for image in os.listdir(r'C:\Desktop\Python\images')]

    def resize_image(self, mode=0):
        if mode == 0:
            img_width = self.curr_img_pixmap.width()
            img_height = self.curr_img_pixmap.height()
            if img_width > self.width():
                self.curr_img_pixmap = self.curr_img_pixmap.scaledToWidth(self.width())
            elif img_height > self.height():
                self.curr_img_pixmap = self.curr_img_pixmap.scaledToHeight(self.height())
            else:
                self.curr_img_pixmap = self.curr_img_pixmap.scaledToHeight(self.height())

    def viewer(self):
        self.viewer_widget = qtw.QMainWindow()
        self.viewer_widget.setCentralWidget(self.image_label)

    def change_image(self, direction):
        current_index = self.images.index(self.curr_img)
        if direction == qtc.Qt.Key_Left:
            if current_index == 0:
                return
            self.curr_img = self.images[current_index-1]
            self.curr_img_pixmap = qtg.QPixmap(os.path.join(r'C:\Desktop\Python\images', self.curr_img))
            self.resize_image(0)
            self.image_label.setPixmap(self.curr_img_pixmap)
        if direction == qtc.Qt.Key_Right:
            print(current_index)
            if current_index == len(self.images)-1:
                return
            self.curr_img = self.images[current_index+1]
            self.curr_img_pixmap = qtg.QPixmap(os.path.join(r'C:\Desktop\Python\images', self.curr_img))
            self.resize_image(0)
            self.image_label.setPixmap(self.curr_img_pixmap)

    def keyPressEvent(self, event):
        if event.key() == qtc.Qt.Key_Left:
            self.change_image(qtc.Qt.Key_Left)
        if event.key() == qtc.Qt.Key_Right:
            self.change_image(qtc.Qt.Key_Right)

    def resizeEvent(self, event):
        self.resize_image(0)
        self.image_label.setPixmap(self.curr_img_pixmap)

if __name__ == '__main__':
    app = qtw.QApplication(sys.argv)
    mw = MainWindow()
    sys.exit(app.exec_())

P.S:代码here不在python中。

【问题讨论】:

  • 查看我对相关帖子的回答:Resizing a window with PyQT5 - how do I reduce the size of a widget to allow the window to be shrunk?(不是 OP 提供的解决方案)。这个概念是 QLabel 不允许调整到比为其设置的像素图更小的尺寸(只有更大的尺寸是可能的),所以最简单的解决方案是使用自定义小部件。
  • @musicamante 我无法评论你的其他帖子,所以我在这里问这个问题:你说使用 QScrollArea 是个坏主意,但如果我想提供放大/缩小功能对于图像, QScrollArea 不是理想的吗?或者有其他方法吗?
  • IF 您还需要缩放功能,那么情况显然非常不同,QScrollArea 显然 可能 有意义,但随后出现了其他问题:如果调整窗口大小会发生什么?它应该保持图像比例和窗口大小之间的当前比率吗?还是应该尝试使“当前规模”适应新的规模?比例尺应该根据最小尺寸(宽度或高度)还是最大尺寸进行调整?

标签: python pyqt5


【解决方案1】:

使用 .scaled 方法与 keepAspectRatio 以及 QLabel 的宽度和高度

import sys
import os
import time
from PyQt5 import Qt
from PyQt5.QtCore import *
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtGui as qtg
from PyQt5 import QtCore as qtc

class MainWindow(qtw.QMainWindow):
    def __init__(self):
        super().__init__()
        self.image_label = qtw.QLabel(alignment=qtc.Qt.AlignCenter)
        self.image_label.setMinimumSize(1, 1)
        self.image_handler()
        self.curr_img = self.images[0]
        self.curr_img_pixmap = qtg.QPixmap(os.path.join(r'C:\Desktop\Python\images', self.curr_img))
        self.image_label.setPixmap(self.curr_img_pixmap.scaled(self.image_label.width(), self.image_label.height(), Qt.KeepAspectRatio,Qt.SmoothTransformation))
        self.viewer()
        self.setCentralWidget(self.viewer_widget)
        self.setStyleSheet("""* {
            background-color: #0d0d0d;
        }
        .QLabel {
            border-style: none;
        }
        .QMainWindow {
            border-style: none;
        }
        """)
        self.show()

    def image_handler(self):
        self.images = [image for image in os.listdir(r'C:\Desktop\Python\images')]

    def viewer(self):
        self.viewer_widget = qtw.QMainWindow()
        self.viewer_widget.setCentralWidget(self.image_label)

    def change_image(self, direction):
        current_index = self.images.index(self.curr_img)
        if direction == qtc.Qt.Key_Left:
            if current_index == 0:
                return
            self.curr_img = self.images[current_index-1]
            self.curr_img_pixmap = qtg.QPixmap(os.path.join(r'C:\Desktop\Python\images', self.curr_img))
            self.image_label.setPixmap(self.curr_img_pixmap.scaled(self.image_label.width(), self.image_label.height(), Qt.KeepAspectRatio,Qt.SmoothTransformation))
        if direction == qtc.Qt.Key_Right:
            if current_index == len(self.images)-1:
                return
            self.curr_img = self.images[current_index+1]
            self.curr_img_pixmap = qtg.QPixmap(os.path.join(r'C:\Desktop\Python\images', self.curr_img))
            self.image_label.setPixmap(self.curr_img_pixmap.scaled(self.image_label.width(), self.image_label.height(), Qt.KeepAspectRatio,Qt.SmoothTransformation))

    def keyPressEvent(self, event):
        if event.key() == qtc.Qt.Key_Left:
            self.change_image(qtc.Qt.Key_Left)
        if event.key() == qtc.Qt.Key_Right:
            self.change_image(qtc.Qt.Key_Right)

    def resizeEvent(self, event):
        #self.resize_image(0)
        print(event)
        self.image_label.setPixmap(self.curr_img_pixmap.scaled(self.image_label.width(), self.image_label.height(), Qt.KeepAspectRatio,Qt.SmoothTransformation))

if __name__ == '__main__':
    app = qtw.QApplication(sys.argv)
    mw = MainWindow()
    sys.exit(app.exec_())

【讨论】:

  • 不幸的是,一旦设置了图像,仍然无法将主窗口的大小调整为小于定义的大小。
  • 还有另一个问题:调整大小不考虑用于像素图的实际小部件 (self.image_label),而是考虑窗口的大小。这可能会变得非常有问题,因为 QMainWindow 可以在其中包含其他小部件(菜单栏、状态栏、停靠小部件和工具栏),结果是这肯定会导致递归。
  • self.image_label.setMinimumSize(1, 1) 解决将窗口大小调整为更小的问题
  • 对于宽度和高度,我将其更改为按照建议采用 Qlabel 宽度和高度
  • 这样更好,但仍然没有完全考虑主窗口的可选小部件:如果显示/隐藏/调整了停靠小部件或工具栏的大小,主窗口将不会收到调整大小事件,结果是图像不会相应地调整大小。这是处理此类事件的主要原因之一应该在正在调整大小的小部件上(通过实现子类或至少通过使用事件过滤器)完成,而不是单独在父级上。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-20
  • 1970-01-01
  • 2015-12-05
  • 1970-01-01
  • 1970-01-01
  • 2019-03-02
相关资源
最近更新 更多