I am trying to use PyQt5 to draw a round gauge (MacOS 11.0.1, Python 3.9). I used the drawArc statement to created the gauge background, so I set the pen width to a large value (70). The resulting arc looks like a horseshoe, presumably because the "pen" is a 70 pixels square, not a line perpendicular to the direction of travel.
Is there a way of creating an arc - in PyQt5 - like the one on the right side of the picture?
I am open to suggestions: the application has already been written with Python+Tkinter, but thanks to the lack of anti-aliasing on Tkinter+Raspberry, I need re-write it.
(Plan B is to continue with PyQt, create a pie slice (drawPie) and cover the centre area with a circle of background colour - but this is not ideal, as it imposes some limitations to my design.)
# importing libraries
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
arcreading = 0
adder = .1
# creating a Gauge class
class Gauge(QMainWindow):
# constructor
def __init__(self):
super().__init__()
timer = QTimer(self) # create a timer object
timer.timeout.connect(self.update) # add action to the timer, update the whole code
timer.start(0) # update cycle in milliseconds
self.setGeometry(200, 200, 600, 600) # window location and size
self.setStyleSheet("background : black;") # background color
# -----------------------
# method for paint event
# -----------------------
def paintEvent(self, event):
global arcreading
global adder
# print('x')
kanvasx = 50 # binding box origin: x
kanvasy = 50 # binding box origin: y
kanvasheight = 150 # binding box height
kanvaswidth = 150 # binding box width
arcsize = 270 # arc angle between start and end.
arcwidth = 70 # arc width
painter = QPainter(self) # create a painter object
painter.setRenderHint(QPainter.Antialiasing) # tune up painter
painter.setPen(QPen(Qt.green, arcwidth)) # set color and width
# ---------- the following lines simulate sensor reading. -----------
if arcreading > arcsize or arcreading < 0: # variable to make arc move
adder = -adder # arcreading corresponds to the
# value to be indicated by the arc.
arcreading = arcreading + adder
# --------------------- end simulation ------------------------------
#print(arcreading)
# drawArc syntax:
# drawArc(x_axis, y_axis, width, length, startAngle, spanAngle)
painter.drawArc(kanvasx, kanvasy, # binding box: x0, y0, pixels
kanvasheight + arcwidth, # binding box: height
kanvaswidth + arcwidth, # binding box: width
int((arcsize + (180 - arcsize) / 2)*16), # arc start point, degrees (?)
int(-arcreading*16)) # arc span
painter.end() # end painter
# Driver code
if __name__ == '__main__':
app = QApplication(sys.argv)
# creating a Gauge object
win = Gauge()
# show
win.show()
exit(app.exec_())
You need to set the capStyle
of the pen with the appropriate Qt.PenCapStyle
, in your case you should use FlatCap
, which ends exactly at the end of the line, while the default is SquareCap
(which covers the end and extends by half the line width):
painter.setPen(QPen(Qt.green, arcwidth, cap=Qt.FlatCap))