我正在尝试创建一个具有两个并排面板的基本程序:一个带有图像,一个带有文本。我使用分离器来调整两个区域的大小,直到完全折叠其中一个区域。这与
QTextEdit
配合得很好。
但是,当我折叠
QGraphicsView
(使用修复除零错误的附加代码)时,图像和我设置为默认值的背景都不会重新出现。我发现自己不知道该怎么做才能使图像和背景重新出现。
这是加载图像后的图像 - 移动分割器也会调整图像的大小(这也是所需的最终状态):
Debug表示
QPixMap
仍有数据,但无法正常显示。我尝试添加self.scene().update()
,但这仍然没有影响结果。
代码:
from PyQt5 import QtCore, QtGui, QtWidgets
class ImageViewer(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super(ImageViewer, self).__init__(parent)
self._empty = True
self._scene = QtWidgets.QGraphicsScene(self)
self._photo = QtWidgets.QGraphicsPixmapItem()
self._scene.addItem(self._photo)
self.setScene(self._scene)
self.setTransformationAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse)
self.setResizeAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setBackgroundBrush(QtGui.QBrush(QtGui.QColor(30, 30, 30)))
self.setFrameShape(QtWidgets.QFrame.NoFrame)
def setPhoto(self, pixmap=None):
if pixmap and not pixmap.isNull():
self._empty = False
self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)
self._photo.setPixmap(pixmap)
self.fitInView()
else:
self._empty = True
self.setDragMode(QtWidgets.QGraphicsView.NoDrag)
self._photo.setPixmap(QtGui.QPixmap())
def fitInView(self, scale=True):
if self._empty:
return
rect = QtCore.QRectF(self._photo.pixmap().rect())
if not rect.isNull():
self.setSceneRect(rect)
viewrect = self.viewport().rect()
scenerect = self.transform().mapRect(rect)
if scenerect.width() == 0 or scenerect.height() == 0:
return
factor = min(viewrect.width() / scenerect.width(), viewrect.height() / scenerect.height())
self.scale(factor, factor)
def resizeEvent(self, event):
if not self._empty:
self.fitInView()
class Window(QtWidgets.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.setWindowTitle("Panel Editor")
self.setGeometry(250, 150, 1600, 1200)
self.centralWidget = QtWidgets.QWidget()
self.setCentralWidget(self.centralWidget)
self.splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
self.viewer = ImageViewer()
self.splitter.addWidget(self.viewer)
self.textEditor = QtWidgets.QTextEdit()
self.splitter.addWidget(self.textEditor)
# Set the initial sizes of the splitter's panels to divide the space equally
self.splitter.setSizes([800, 800])
layout = QtWidgets.QVBoxLayout(self.centralWidget)
layout.addWidget(self.splitter)
self.createMenu()
def createMenu(self):
self.menuBar = QtWidgets.QMenuBar()
self.setMenuBar(self.menuBar)
fileMenu = self.menuBar.addMenu('&File')
openAction = QtWidgets.QAction('&Open', self)
openAction.setShortcut('Ctrl+O')
openAction.setStatusTip('Open image')
openAction.triggered.connect(self.openImage)
fileMenu.addAction(openAction)
def openImage(self):
imagePath, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Open Image", "", "Image Files (*.png *.jpg *.bmp)")
if imagePath:
self.viewer.setPhoto(QtGui.QPixmap(imagePath))
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
您只是检查场景,但不能确保视口大小实际上有效。结果是,您最终可能会得到视口的空尺寸(宽度和/或高度),这将导致
viewrect/scenerect
分数等于零,这将成为因子。
由于 current 因子也用于
self.transform().mapRect(rect)
,恢复视图的大小将不会有任何效果,因为当前变换使用上面的 0 因子。
解决方案是仅在视口矩形有效时应用变换(高度和宽度> 0),这可以通过检查这些值或辅助函数
isValid()
或isNull()
来完成
。
或者,只需将比例设置为
factor > 0
即可。
基于musicamante的优秀解决方案,我修改了
fitInView
以使其能够与以下代码一起使用:
def fitInView(self, scale=True):
print("fitInView called.")
if self._empty:
print("No photo to fit in view.")
return
rect = QtCore.QRectF(self._photo.pixmap().rect())
if not rect.isNull():
self.setSceneRect(rect)
viewrect = self.viewport().rect()
# Ensure the viewrect is valid before proceeding
if not viewrect.isValid():
print("Viewport rect is invalid; cannot fitInView.")
return
scenerect = self.transform().mapRect(rect)
if scenerect.width() > 0 and scenerect.height() > 0:
factor = min(viewrect.width() / scenerect.width(), viewrect.height() / scenerect.height())
# Apply scaling only if factor is greater than 0
if factor > 0:
self.scale(factor, factor)
print(f"Photo fitted with factor: {factor}")
else:
print("Scaling factor is zero or negative; cannot fitInView.")
else:
print("Scene rect is zero sized; cannot fitInView.")
else:
print("Pixmap rect is null; cannot fitInView.")