1

I layout a bunch of nodes on a QGraphicsScene. The nodes are basic ellipses (QGraphicsEllipseItems). It works reasonably well.

However I would like to know how to size the ellipses. Currently I have a hard-coded radius to 80 units this works fine when there are the number of ellipses are few hundred, however when I have a few thousand ellipses it looks all wrong as they are too small for the scale of the scene. tiny ellipses Conversely when there are only a few 10s the scene being smaller the ellipses are way to large.

I am looking to find a formula that better balances the size of an ellipse, with the number of ellipses on the scene and the scale of the scene.

Also as I zoom in and out I would like the ellipses to remain appropriately sized.

Can anyone advise on how to best achieve a balanced arrangement?

NoDataDumpNoContribution
  • 10,591
  • 9
  • 64
  • 104
user595985
  • 1,543
  • 4
  • 29
  • 55
  • The nodes are tiny because you made them tiny, you could easily make them larger (do not forget to call setSceneRect or Qt will try keep the scene in the center). For letting the ellipses remain appropriately sized while zooming, see my answer. – NoDataDumpNoContribution Feb 03 '15 at 22:45

1 Answers1

0

The scene has a certain bounding rectangle that encloses all graphics items you put into it while the view has a certain size on the screen.

Between the scene and the view there is a transformation matrix (2x3 for scaling, rotate, shear and translation). You can get it by QGraphicsView.transform().

Now if you put more ellipses into your plot increasing the scene size but want to still see all of them, you must zoom out and accordingly the widths of the ellipses will shrink too.

You don't want that. Okay, so why not resizing them (according to the current scaling factor) everytime the scale changes. Well, this is probably not very efficient.

The better solution is to not change the scale of the view, but just scale the positions manually while keeping the zoom fixed. That way no properties of the items except their position has to be changed.

Example (using PySide and Python 3 but easily adjustable to PyQt and 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_()

With the mousewheel you can scale the positions and then it looks like this:

enter image description here

As for the balance of size and number of ellipses - well it's all your choice. There is no generic rule. I recommend to not make the ellipses larger than the distance between the ellipses or they will overlap. In general I work with scene coordinates that are 1:1 with pixel sizes of the view (as I did in the example above, 400 pixels width of the view, 400 units width of the scene rectangle). Then I can easily imagine what a size of an ellipse of 10 will be, that is 10 pixels. If I want more I use more and if I want less I use less. But there is no rule for it, it's up to what you want.

NoDataDumpNoContribution
  • 10,591
  • 9
  • 64
  • 104