Warm tip: This article is reproduced from serverfault.com, please click

PyQt5 drawArc with wide "pen"

发布于 2020-11-28 18:33:47

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_())

enter image description here

Questioner
nandomtl
Viewed
0
musicamante 2020-11-29 03:14:40

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))