PyQt:如何拉伸 QGraphicsView 和 QGraphicsScene 小部件的宽度和高度? [英] PyQt: How to stretch the width and height of a QGraphicsView and QGraphicsScene widget?
问题描述
我正在尝试创建一个可拉伸到窗口宽度和高度的网格小部件.网格的大小(当前为 14x49)可能会发生变化,但我希望小部件的整体大小保持不变.
I am trying to create a grid widget that stretches to the width and height of the window. The size of the grid (currently 14x49) is subject to change but I want the overall size of the widget to stay the same.
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QLayout,
QGridLayout, QSizePolicy, QGraphicsScene, QGraphicsView
from PyQt5.QtCore import QCoreApplication, QSize, Qt, QRectF, QPointF, QSizeF
from PyQt5.QtGui import QColor, QPen, QBrush, qRgb
class Map(QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.initUI()
def initUI(self):
self.setMinimumSize(500, 500) # min-size of the widget
self.columns = 14 # num of columns in grid
self.rows = 49 # num of rows in grid
def resizeEvent(self, event):
# compute the square size based on the aspect ratio, assuming that the
reference = self.width() * self.rows / self.columns
if reference > self.height():
# the window is larger than the aspect ratio
# use the height as a reference (minus 1 pixel)
self.squareSize = (self.height() - 1) / self.rows
else:
# the opposite
self.squareSize = (self.width() - 1) / self.columns
def paintEvent(self, event):
grid = QGridLayout()
self.sceneWithPen(grid)
self.setLayout(grid)
# creates the grid of squares
def sceneWithPen(self, grid):
scene = QGraphicsScene()
w = QGraphicsView()
w.setScene(scene)
side = self.squareSize
brush = QBrush(QColor(qRgb(255, 255, 255))) # background color of square
pen = QPen(Qt.black) # border color of square
for i in range(self.rows):
for j in range(self.columns):
r = QRectF(QPointF(
i*side, j*side), QSizeF(side, side)) # each square
scene.addRect(r, pen, brush)
grid.addWidget(w)
if __name__ == "__main__":
app = QApplication(sys.argv)
view = Map()
view.show()
sys.exit(app.exec_())
我希望小部件的外观:
推荐答案
你的方法比它需要的要复杂得多,并且有很多问题(其中一些非常重要).
Your approach is much more complex than it needs, and there are various issues about it (some of them quite important).
首先,不需要每次都计算正方形的大小,因为 QGraphicsView 可以通过使用 fitInView()
,默认忽略纵横比.只需使用适合您需求的任意正方形大小即可.
First of all, there's no need to compute the size of the squares each time, since QGraphicsView can do that by using fitInView()
, which by default ignores the aspect ratio. Just use an arbitrary square size that fits your needs.
然后,您应该切勿在 paintEvent
中创建和添加小部件,因为这可能会导致递归.
Then, you should NEVER create and add widgets in a paintEvent
, as it might cause recursion.
在小部件上设置布局后,除非绝对必要,否则不应再设置其他布局(无论如何,不应那样做).
Once a layout is set on a widget, you should not set another one, unless absolutely necessary (and, anyway, it shouldn't be done like that).
当使用 addRect
向 graphicsScene 添加矩形时,通常不需要先创建 QRectF,因为您可以使用接受坐标和大小的便利函数(Qt 会自动创建 QRectF无论如何在 C++ 方面,这可能会稍微快一些).
When adding a rect to a graphicsScene using addRect
, there's usually no need to create a QRectF first, as you can just use the convenience function that accepts coordinate and size (Qt will automatically create the QRectF anyway on the C++ side, which might be slightly faster).
另一方面,由于您要创建多个相同大小的矩形,您可以只创建一个 QRectF,然后使用 translated()
设置坐标.
On the other hand, since you're creating multiple rectangles of the same size, you could just create a single QRectF and then use translated()
to set the coordinates.
当这些是现有变量或常量时,通常建议使用 QPointF 和 QSizeF 创建 QRectF,否则您可以使用基本的 QRectF(x, y, width, height)
构造函数.
Creating a QRectF with QPointF and QSizeF is usually suggested when those are existing variables or constants, otherwise you can just use the basic QRectF(x, y, width, height)
constructor.
class Map(QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.initUI()
def initUI(self):
self.setMinimumSize(500, 500) # min-size of the widget
self.columns = 14 # num of columns in grid
self.rows = 49 # num of rows in grid
grid = QGridLayout(self)
self.view = QGraphicsView()
grid.addWidget(self.view)
self.view.setRenderHints(QPainter.Antialiasing)
self.scene = QGraphicsScene()
self.view.setScene(self.scene)
brush = QBrush(QColor(qRgb(255, 255, 255))) # background color of square
pen = QPen(Qt.black) # border color of square
side = 10
rect = QRectF(0, 0, side, side)
for i in range(self.rows):
for j in range(self.columns):
self.scene.addRect(rect.translated(i * side, j * side), pen, brush)
# this is required to ensure that fitInView works on first shown too
self.resizeScene()
def resizeScene(self):
self.view.fitInView(self.scene.sceneRect())
def resizeEvent(self, event):
# call fitInView each time the widget is resized
self.resizeScene()
def showEvent(self, event):
# call fitInView each time the widget is shown
self.resizeScene()
这篇关于PyQt:如何拉伸 QGraphicsView 和 QGraphicsScene 小部件的宽度和高度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!