PyQt:最大化window时如何防止处理多个调整大小事件?
PyQt: How to prevent processing multiple resize events when maximizing a window?
我有一个 QMainWindow
包含一个 child QWidget
包含一个 QLabel
.
当 window 最大化时(例如,通过单击 window 上的最大化图标),QLabel.resizeEvent()
处理程序被多次调用(据说是跟随window 直到占用整个桌面 space)。
事件处理程序中的代码调用 setPixmap()
来缩放标签像素图。这是一个相对较长的操作,会减慢该过程。标签代码:
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QLabel, QFrame, QGridLayout
from PyQt5.QtGui import QImageReader, QPixmap
class DisplayArea(QLabel):
def __init__(self):
super().__init__()
self.pix_map = None
self.init_ui()
def init_ui(self):
self.setMinimumSize(1, 1)
self.setStyleSheet("border:1px solid black;")
def set_image(self, image):
self.pix_map = QPixmap.fromImage(image)
self.scale_image(self.size())
def scale_image(self, size):
if self.pix_map is None:
return
scaled = self.pix_map.scaled(size, Qt.KeepAspectRatio)
self.setPixmap(scaled)
def resizeEvent(self, e):
self.scale_image(e.size())
super().resizeEvent(e)
是否有可能在 window 达到其最终大小时仅处理一次事件?
问题是resizeEvent在window最大化的时候被调用了很多次,同样的次数就是你调用的scale_image。一种可能是不更新,除非经过一段时间。在以下示例中,仅调整大于 100 毫秒(您必须校准的时间)的时间:
from PyQt5 import QtCore, QtGui, QtWidgets
class DisplayArea(QtWidgets.QLabel):
def __init__(self):
super().__init__()
self.pix_map = QtGui.QPixmap()
self._flag = False
self.init_ui()
def init_ui(self):
self.setMinimumSize(1, 1)
self.setStyleSheet("border:1px solid black;")
def set_image(self, image):
self.pix_map = QtGui.QPixmap.fromImage(image)
self.scale_image()
def scale_image(self):
if self.pix_map.isNull():
return
scaled = self.pix_map.scaled(self.size(), QtCore.Qt.KeepAspectRatio)
self.setPixmap(scaled)
def resizeEvent(self, e):
if not self._flag:
self._flag = True
self.scale_image()
QtCore.QTimer.singleShot(100, lambda: setattr(self, "_flag", False))
super().resizeEvent(e)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = QtWidgets.QMainWindow()
da = DisplayArea()
da.set_image(QtGui.QImage("logo.png"))
w.setCentralWidget(da)
w.show()
sys.exit(app.exec_())
我有一个 QMainWindow
包含一个 child QWidget
包含一个 QLabel
.
当 window 最大化时(例如,通过单击 window 上的最大化图标),QLabel.resizeEvent()
处理程序被多次调用(据说是跟随window 直到占用整个桌面 space)。
事件处理程序中的代码调用 setPixmap()
来缩放标签像素图。这是一个相对较长的操作,会减慢该过程。标签代码:
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QLabel, QFrame, QGridLayout
from PyQt5.QtGui import QImageReader, QPixmap
class DisplayArea(QLabel):
def __init__(self):
super().__init__()
self.pix_map = None
self.init_ui()
def init_ui(self):
self.setMinimumSize(1, 1)
self.setStyleSheet("border:1px solid black;")
def set_image(self, image):
self.pix_map = QPixmap.fromImage(image)
self.scale_image(self.size())
def scale_image(self, size):
if self.pix_map is None:
return
scaled = self.pix_map.scaled(size, Qt.KeepAspectRatio)
self.setPixmap(scaled)
def resizeEvent(self, e):
self.scale_image(e.size())
super().resizeEvent(e)
是否有可能在 window 达到其最终大小时仅处理一次事件?
问题是resizeEvent在window最大化的时候被调用了很多次,同样的次数就是你调用的scale_image。一种可能是不更新,除非经过一段时间。在以下示例中,仅调整大于 100 毫秒(您必须校准的时间)的时间:
from PyQt5 import QtCore, QtGui, QtWidgets
class DisplayArea(QtWidgets.QLabel):
def __init__(self):
super().__init__()
self.pix_map = QtGui.QPixmap()
self._flag = False
self.init_ui()
def init_ui(self):
self.setMinimumSize(1, 1)
self.setStyleSheet("border:1px solid black;")
def set_image(self, image):
self.pix_map = QtGui.QPixmap.fromImage(image)
self.scale_image()
def scale_image(self):
if self.pix_map.isNull():
return
scaled = self.pix_map.scaled(self.size(), QtCore.Qt.KeepAspectRatio)
self.setPixmap(scaled)
def resizeEvent(self, e):
if not self._flag:
self._flag = True
self.scale_image()
QtCore.QTimer.singleShot(100, lambda: setattr(self, "_flag", False))
super().resizeEvent(e)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = QtWidgets.QMainWindow()
da = DisplayArea()
da.set_image(QtGui.QImage("logo.png"))
w.setCentralWidget(da)
w.show()
sys.exit(app.exec_())