I am trying to make a simple speedometer using PyQt5 and Qt Designer. I have a problem due to the rotation of the speedometer arrow self.arrow
.
This is the code:
class MyWin(QtWidgets.QMainWindow):
def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.speedSlider.valueChanged.connect(self.valuechange)
scene = QGraphicsScene()
scene.setSceneRect(0, 0, self.width(), self.height())
self.pixmap = QPixmap(":/img/img/speed_arrow.png")
self.arrow = scene.addPixmap(self.pixmap)
graphicsView = QGraphicsView(scene, self.ui.centralwidget)
graphicsView.setStyleSheet( "background-image:url(:/img/img/central1.png);\n"
"background-repeat:no-repeat;\n"
"background-position: center;\n"
"\n"
"border:none;")
self.ui.gridLayout.addWidget(graphicsView)
def valuechange(self):
angel = self.ui.speedSlider.value()
xform = QTransform()
xform.rotate(angel)
xformed_pixmap = self.pixmap.transformed(xform, Qt.SmoothTransformation)
self.arrow.setPixmap(xformed_pixmap)
#print(self.arrow.sceneBoundingRect())
Instead of drawing a speedometer arrow in the code itself, I loaded a .
I also added a slider self.ui.speedSlider
with which the angle of rotation should be determined.
When I move the slider, the rotation of the arrow is actually achieved. The problem is that the arrow does not rotate around its center.
How to fix the center of rotation so that it is always in the center of the arrow self.arrow
?
This is the Ui_MainWindow code:
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
MainWindow.setStyleSheet("background-image:url(:/img/img/bgd.png);\n"
"possition:center;")
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.speedSlider = QtWidgets.QSlider(self.centralwidget)
self.speedSlider.setMaximum(99)
self.speedSlider.setOrientation(QtCore.Qt.Horizontal)
self.speedSlider.setObjectName("speedSlider")
self.gridLayout.addWidget(self.speedSlider, 1, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
Arrow
Central1
Don't transform the pixmap whenever the value changes. Transforming the pixmap happens in the local pixmap coordinate system and only complicates things.
Instead, set the rotation on self.arrow
.
self.arrow.setTransformOriginPoint()
to set the origin of the rotation to the center of the needle's base (so almost the width of your pixmap, and half its height). Do this directly after creating the arrow.self.arrow.setRotation()
whenever the value changes. It will rotate the arrow item around its origin point which is the needle's base.More information about transforms for QGraphicsItems can be found here.