【发布时间】:2020-04-27 07:05:09
【问题描述】:
我有一个 QMdiSubWindow,它包含一个 QTabWidget,它在一个带有 QHBoxLayout 的小部件内包含 QGraphicsView。子窗口位于我的主窗口的 mdi 区域中。我的目标是为 QGraphicScene 设置一个固定大小,具体取决于我使用的纸张大小。 然后,视图应该与场景的大小一致,如果该区域可以适合总可用 mdi 区域,则不显示滚动条,也调整子窗口的大小,或者应该调整大小以填充可用区域,也调整子窗口的大小,并且应该显示滚动条以导航到剩余空间。
我目前的方法是首先调整 mdi 子窗口的大小,然后调用调整窗口 QTabWidget 中当前活动小部件的大小。 这一切都是按照musicamante的实现来完成的。 当前小部件选择父(QStackedWidget)的父(QTabWidget)的父(QMdiSubWindow)的矩形(首先调整大小)和QGraphicsScene的尺寸之间的最小值,该尺寸在我设置尺寸时更新。
-> 根据用户输入设置 QGraphicsScene 尺寸
-> 调整子窗口大小
-> 调整 QGraphicsView 的大小
我在我的程序上使用相同的逻辑,它根本无法显示滚动条,并且视图扩展以适应 QGraphicsScene 尽管被告知要改为子窗口的大小(子窗口的大小正确),以及下面的示例,它们确实根据需要显示,但被部分剪掉。
from PyQt5 import QtWidgets, QtCore, QtGui
paperSizes = {
"A0": {
"72": [2384, 3370],
"96": [3179, 4494],
"150": [4967, 7022],
"300": [9933, 14043]
},
"A1": {
"72": [1684, 2384],
"96": [2245, 3179],
"150": [3508, 4967],
"300": [7016, 9933]
},
"A2": {
"72": [1191, 1684],
"96": [1587, 2245],
"150": [2480, 3508],
"300": [4960, 7016]
},
"A3": {
"72": [842, 1191],
"96": [1123, 1587],
"150": [1754, 2480],
"300": [3508, 4960]
},
"A4": {
"72": [595, 842],
"96": [794, 1123],
"150": [1240, 1754],
"300": [2480, 3508]
}
}
class canvas(QtWidgets.QWidget):
def __init__(self, parent=None, size= 'A4', ppi= '72'):
super(canvas, self).__init__(parent)
self._ppi = ppi
self._canvasSize = size
self.painter = QtWidgets.QGraphicsScene()
self.painter.setBackgroundBrush(QtGui.QBrush(QtCore.Qt.white))
self.view = QtWidgets.QGraphicsView(self.painter)
# self.view.setMinimumSize(595, 842)
self.layout = QtWidgets.QHBoxLayout(self)
self.layout.addWidget(self.view, stretch = 1, alignment= QtCore.Qt.AlignCenter)
self.setLayout(self.layout)
self.painter.setSceneRect(0, 0, *paperSizes[self.canvasSize][self.ppi])
def resizeView(self, w, h):
self.painter.setSceneRect(0, 0, w, h)
self.adjustView()
def adjustView(self):
self.view.setSceneRect(0, 0, self.painter.sceneRect().width() - self.view.frameWidth() * 2,
self.painter.sceneRect().height())
# give the view some time to adjust itself
QtWidgets.QApplication.processEvents()
width = self.painter.sceneRect().width() + self.view.frameWidth()*2
if self.view.verticalScrollBar().isVisible():
width += self.style().pixelMetric(QtWidgets.QStyle.PM_ScrollBarExtent)
height = self.painter.sceneRect().height() + self.view.frameWidth()*2
if self.view.verticalScrollBar().isVisible():
height += self.style().pixelMetric(QtWidgets.QStyle.PM_ScrollBarExtent)
self.view.setFixedWidth(min(self.parent().rect().width() - self.view.frameWidth()*2, width))
self.view.setFixedHeight(min(self.parent().rect().height()- self.view.frameWidth()*2, height))
def resizeEvent(self, event):
self.adjustView()
def setCanvasSize(self, size):
self.canvasSize = size
def setCanvasPPI(self, ppi):
self.ppi = ppi
@property
def canvasSize(self):
return self._canvasSize
@property
def ppi(self):
return self._ppi
@canvasSize.setter
def canvasSize(self, size):
self._canvasSize = size
if self.painter:
self.resizeView(*paperSizes[self.canvasSize][self.ppi])
@ppi.setter
def ppi(self, ppi):
self._ppi = ppi
if self.painter:
self.resizeView(*paperSizes[self.canvasSize][self.ppi])
@property
def dimensions(self):
#returns the dimension of the current scene
return self.painter.sceneRect().width(), self.painter.sceneRect().height()
class AppDemo(QtWidgets.QMainWindow):
def __init__(self):
super(AppDemo, self).__init__()
self.centralwidget = canvas(self)
width, height = paperSizes['A4']['72']
wsetter = min(1800, width - self.centralwidget.view.frameWidth()*2)
hsetter = min(900, height - self.centralwidget.view.frameWidth()*2)
self.setFixedSize(wsetter, hsetter)
self.centralwidget.resizeView(width, height)
self.setCentralWidget(self.centralwidget)
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.resizer)
self.show()
def resizer(self, point):
width, height = paperSizes['A0']['300']
wsetter = min(1800, width - self.centralwidget.view.frameWidth()*2)
hsetter = min(900, height - self.centralwidget.view.frameWidth()*2)
self.setFixedSize(wsetter, hsetter)
self.centralWidget().resizeView(width, height)
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
w = AppDemo()
w.setWindowTitle('AppDemo')
w.centralwidget.resizeView(*paperSizes['A0']['72'])
w.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
【问题讨论】:
-
拉伸总是根据可用大小调整大小,这是使用其他同级小部件大小策略计算的。现在,根据您的代码,您只是更改视图的场景矩形,您不能相应地为图形视图设置固定宽度吗?
-
所以在设置场景矩形的同时设置一个固定宽度?
-
是的,完全正确。设置视图的场景矩形只会改变视口上可见的场景区域,但不会影响视图的大小。请注意,如果您需要根据场景设置精确的宽度,则必须考虑视口的边距(包括 QFrame lineWidth 以及由于场景内容和翻译管理可能至少额外的像素),以便显示滚动条仅在真正需要时。
-
这种部分解决了我的问题,但由于某种原因,当我将视图的高度设置为父级的高度时,当有宽度可以扩展时,仍然会出现一些实心滚动条滚动条没有空间移动。此外,当小部件初始化时,宽度很奇怪,我必须在小部件添加到窗口后再次调用我的调整大小函数来修复它....
-
我建议你编辑你的代码并提供一个完整的minimal, reproducible example,这样我们就可以试着了解那里到底发生了什么。
标签: python-3.x pyqt5