在不更改其他属性的情况下缩放QGraphicsScene上图形项的位置

时间:2015-02-03 21:37:34

标签: python qt pyqt scaling qgraphicsscene

我在QGraphicsScene上布局了一堆节点。节点是基本椭圆(QGraphicsEllipseItems)。它运作得相当好。

但是我想知道如何调整省略号的大小。目前我有一个硬编码的半径到80个单位,当椭圆的数量是几百时,这很好用,但是当我有几千个椭圆时,它看起来都错了,因为它们对于场景的比例来说太小了。 tiny ellipses 相反,当只有几十个场景较小时,椭圆会变大。

我希望找到一个更好地平衡椭圆大小的公式,以及场景中的椭圆数和场景的比例。

另外,当我放大和缩小时,我希望椭圆保持适当的大小。

有人可以就如何最佳地实现平衡安排提出建议吗?

1 个答案:

答案 0 :(得分:0)

场景有一个特定的边界矩形,当视图在屏幕上有一定的大小时,它会包含您放入其中的所有图形项目。

在场景和视图之间有一个变换矩阵(2x3用于缩放,旋转,剪切和平移)。你可以通过QGraphicsView.transform()获得它。

现在,如果您在绘图中添加更多的椭圆以增加场景大小但仍希望仍能看到所有这些,则必须缩小,因此椭圆的宽度也会缩小。

你不想那样。好的,那么为什么不在每次比例变化时调整它们(根据当前的比例因子)。嗯,这可能效率不高。

更好的解决方案是不改变视图的比例,而只是手动缩放位置,同时保持缩放固定。这样,除了位置之外,不得更改任何物品的属性。

示例(使用PySide和Python 3,但很容易调整到PyQt和Python 2):

from PySide import QtGui, QtCore
import random

class MyGraphicsView(QtGui.QGraphicsView):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def wheelEvent(self, event):
        if event.delta() > 0:
            scaling = 1.1
        else:
            scaling = 1 / 1.1

        # reposition all items in scene
        for item in self.scene().items():
            r = item.rect()
            item.setRect(QtCore.QRectF(r.x() * scaling, r.y() * scaling, r.width(), r.height()))

app = QtGui.QApplication([])

scene = QtGui.QGraphicsScene()
scene.setSceneRect(-200, -200, 400, 400)
for i in range(100):
    rect = QtCore.QRectF(random.uniform(-180, 180), random.uniform(-180, 180), 10, 10)
    scene.addEllipse(rect)

view = MyGraphicsView(scene)
view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
view.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
view.resize(400, 400)
view.show()

app.exec_()

使用鼠标滚轮可以缩放位置,然后它看起来像这样:

enter image description here

关于椭圆的大小和数量的平衡 - 这是你的选择。没有通用规则。我建议不要使椭圆大于椭圆之间的距离,否则它们会重叠。一般来说,我使用1:1的场景坐标来处理视图的像素大小(正如我在上面的示例中所做的那样,视图的宽度为400像素,场景矩形的宽度为400)。然后我可以很容易地想象出10个椭圆的大小,即10个像素。如果我想要更多,我会使用更多,如果我想要更少,我会少用。但是没有规则,这取决于你想要的。