Reputation: 1079
I'm trying to plot on a QGraphicScene data which can, depending on situation, vary by orders of magnitude. Since the pen I'm using is cosmetic I'd expect the view to be independent of the magnitude of the data. But what I get instead is this:
Sine wave with noise multiplied by 50000:
Sine wave with noise multiplied by 50:
However, if I zoom in to either of these plots (same amount of zooming in both), I eventually reach a level when both images look the same:
What is going on here? Why is the width of the pen changing just because the data values are bigger. And why does the scaling disappear when zoomed in?
The code to reproduce this follows. Left clicking on the plot zooms in, right clicking zooms out.
import sys
from PyQt4 import QtGui as QG
from PyQt4 import QtCore as QC
import numpy as n
class ZoomView(QG.QGraphicsView):
"""Zoomable QGraphicsView"""
def mouseReleaseEvent(self,event):
if event.button() == QC.Qt.LeftButton:
self.scale(1.5,1)
elif event.button() == QC.Qt.RightButton:
self.scale(1/1.5,1)
class MainUI(QG.QDialog):
def __init__(self, parent=None):
super(MainUI, self).__init__(parent)
layout = QG.QVBoxLayout()
self.setLayout(layout)
button_layout = QG.QHBoxLayout()
pb3 = QG.QPushButton('add plot')
button_layout.addWidget(pb3)
layout.addLayout(button_layout)
pb3.clicked.connect(self.scene_maker_singleshot)
scene = QG.QGraphicsScene()
view = ZoomView(self)
view.setTransformationAnchor(QG.QGraphicsView.AnchorUnderMouse)
view.setRenderHint(QG.QPainter.Antialiasing)
layout.addWidget(view)
view.setScene(scene)
self.view = view
self.scene = scene
def scene_maker_singleshot(self):
"""Draw scene and fit in view"""
t1 = 50
t2 = 100
QC.QTimer.singleShot(t1, self.make_scene)
QC.QTimer.singleShot(t2, lambda: self.view.fitInView(self.view.sceneRect()))
def make_scene(self):
scale = 50
#scale = 50000
noise_amp = 0.2*scale
points = 1000
xdata = n.arange(points)
#generate sine data and random noise
ydata = n.sin(xdata/(points/10.))*scale +\
n.random.randint(noise_amp, size=points)
pen = QG.QPen(QG.QColor("red"))
for i in xrange(1, xdata.size):
self.scene.addLine(xdata[i-1], ydata[i-1], xdata[i], ydata[i], pen)
if __name__=="__main__":
app = QG.QApplication(sys.argv)
gui = MainUI()
gui.setFixedSize(500,500)
gui.show()
app.exec_()
Upvotes: 5
Views: 1813
Reputation: 484
Just like Mad Physicist told you, set the pen to cosmetic or line-width of 0 (are equal in the behavior) and you have a non-scaling pen.
>> pen.setCosmetic(True);
Upvotes: 5